現在、本番環境ではAvroデータ形式を使用しています。 Avroを使用するいくつかの優れた点のうち、スキーマの進化に優れていることがわかっています。
現在、ランダムな列を読み取る際の効率のため、Parquet formatを評価しています。ですから、先に進む前に私たちの懸念はまだスキーマの進化です。
スキーマの進化が寄木細工で可能かどうか、はいHowが可能であれば、誰でも知っていますか?いいえWhy.
一部の resources は可能であると主張しますが、は最後にのみ列を追加できます。
これは何を意味するのでしょうか?
スキーマの進化は(非常に)高価になる可能性があります。
スキーマを把握するためには、基本的にすべての寄木細工のファイルを読み取り、読み取り中にスキーマを調整/マージする必要がありますが、データセット内のファイル数や列数によってはコストがかかる場合があります。
したがって、 Spark 1.5 であるため、デフォルトでは schema merging がオフになりました。いつでも元に戻すことができます)。
スキーマのマージは比較的高価な操作であり、ほとんどの場合必要ではないため、1.5.0からデフォルトで無効にしました。
スキーマを進化させなくても、1つの寄木細工のファイルからスキーマを読み取ることができ、残りのファイルを読み取る間は同じままであると想定します。
寄木細工のスキーマの進化は実装依存です。
たとえば、Hiveにはノブparquet.column.index.access=false
があり、列インデックスではなく列名でスキーマをマップするように設定できます。
その後、追加するだけでなく、列も削除できます。
前述したように、実装に依存します。たとえば、Impalaはそのような寄木細工のテーブルを正しく読み取りません(最近のImpala 2.6リリースで修正されました)[ Reference ]。
バージョン2.0.2のApache Sparkは、まだ列の追加のみをサポートしているようです:[ Reference ]
ユーザーは単純なスキーマから開始し、必要に応じて徐々にスキーマに列を追加できます。このようにして、ユーザーは、異なるが相互に互換性のあるスキーマを持つ複数のParquetファイルになる可能性があります。 Parquetデータソースは、このケースを自動的に検出し、これらすべてのファイルのスキーマをマージできるようになりました。
PS:スキーマの変更により俊敏性を高めるために何人かの人々が見たことは、上にviewを作成することです2つ(またはそれ以上)の異なるが互換性のあるスキーマを1つの共通スキーマにマッピングする実際の寄木細工のテーブル。
新しいリリースで1つの新しいフィールド(registration_date
)を追加し、別の列(last_login_date
)をドロップしたとします。これは次のようになります。
CREATE VIEW datamart.unified_fact_vw
AS
SELECT f1..., NULL as registration_date
FROM datamart.unified_fact_schema1 f1
UNION ALL
SELECT f2..., NULL as last_login_date
FROM datamart.unified_fact_schema2 f2
;
あなたはアイデアを得た。嬉しいことに、Hadoopダイアレクト(上記のHive、Impala、Sparkなど)のすべてのsqlで同じように機能し、Parquetテーブル(列ストレージ、述語プッシュダウンなど)のすべての利点があります。
P.P.S:この回答をより完全にするためにSparkが作成できるcommon_metadata
サマリーファイルに関する情報を追加します。
SPARK-15719をご覧ください
寄木細工の要約ファイルは、最近では特に有用ではありません。
- when schema merging is disabled, we assume
schema of all Parquet part-files are identical,
thus we can read the footer from any part-files.
- when schema merging is enabled, we need to read footers
of all files anyway to do the merge.
On the other hand, writing summary files can be expensive,
because footers of all part-files must be read and merged.
This is particularly costly when appending a small dataset
to a large existing Parquet dataset.
したがって、いくつかのポイントはcommon_metadata
を有効にすることに反対です:
異なるスキーマが混在するParquetファイルでディレクトリが構成されている場合、_common_metadataを使用すると、個々のファイルのスキーマを読み取らずに、ディレクトリ全体の適切なスキーマを理解できます。 HiveとImpalaは、Hiveメタストアから前述のファイルのSQLスキーマにアクセスできるため、個々のファイルの処理をすぐに開始でき、共通のスキーマを事前に調べるのではなく、読み取り時に各ファイルをSQLスキーマと照合できます。これにより、HiveとImpalaに共通のメタデータ機能が不要になります。
SparkはSQLスキーマなしでParquetファイルを処理しますが(SparkSQLを使用しない限り)、理論的には_common_metadataの恩恵を受ける可能性がありますが、この機能は依然として役に立たないとみなされ、その結果、SPARK-15719でデフォルトで無効になりました。
この機能がクエリに有用であったとしても、それはまだ書き込み中の負担です。メタデータを維持する必要がありますが、これは遅いだけでなく、競合状態やその他の同時実行の問題が発生しやすく、原子性の保証が不足しており、古いメタデータや一貫性のないメタデータによるデータの正確性の問題につながりやすくなります。
この機能は文書化されておらず、非推奨と見なされているようです(そもそも公式にはまったくサポートされていないようです。また、サポートされていない機能も非推奨ではありません。
Clouderaのエンジニアの1人から:「common_metadata
ファイルが存在する場合、各フッターを見るのを避けるために、読み取り側で動作が変更されたかどうかはわかりません。巨大なボトルネックであり、お客様に多くの問題を引き起こしています。そのメタデータファイルを生成しようとして気にしないことを強くお勧めします。」
「_common_metadata」および「_metadata」ファイルはSpark固有であり、たとえばImpalaやHive、およびおそらく他のエンジンによって書き込まれません。
ただし、Sparkの要約メタデータファイルには、上記の同時実行性やその他の問題がない場合、たとえばいくつかのストリーミングユースケースなど、まだユースケースがある場合があります。スパーク。
上記の答えに加えて、他のオプションは設定することです
"spark.hadoop.parquet.enable.summary-metadata" to "true"
これは、ファイルを書き込むときにスキーマを使用してサマリーファイルを作成します。保存すると、ファイルの要約ファイルが表示されます'_metadata'
および'_common_metadata'
。 _common_metadata
は、寄木細工のファイルを読むたびに読み取られる圧縮されたスキーマです。すでにスキーマを持っているので、これにより非常に高速に読み取れます。 Sparkは、これらのスキーマファイルが存在する場合、スキーマを取得するために検索します。
Spark=はすべてのファイルのスキーマをマージし、これらのスキーマファイルを作成する必要があるため、書き込みが非常に遅くなることに注意してください。
寄木細工のスキーマが変更された同様の状況がありました。スキーマファイルを生成し、true
に戻すように、スキーマの変更後しばらくの間、上記の構成をfalse
に設定しました。遅い書き込みで妥協する必要がありましたが、スキーマファイルが生成された後、false
に設定することで目的を果たしました。また、ファイルをより速く読むことができます。