半構造化データをモデル化する
この記事では、組織でデータがどのように使用されるかに応じて、半構造化データの格納パターンを推奨します。 Databricks には、半構造化データ、ネストされたデータ、および複雑なデータを操作するための関数、ネイティブ データ型、クエリ構文が用意されています。
次の考慮事項は、使用するパターンに影響します。
- データソースのフィールドやタイプは頻繁に変更されますか?
- データソースには、合計でいくつのユニークなフィールドが含まれていますか?
- 書き込みまたは読み取りのワークロードを最適化する必要がありますか?
Databricks では、ダウンストリーム クエリ用にデータを Delta テーブルとして格納することをお勧めします。
バリアントを使用
Databricks Runtime 15.3 以降では、 VARIANT
型を使用して、読み取りと書き込みで JSON 文字列よりも優れた最適化されたエンコードを使用して、半構造化 JSON データを格納できます。
VARIANT
型には、JSON 文字列と同様のアプリケーションがあります。一部のワークロードでは、構造体、マップ、配列を使用することで、特に最適化されたデータ レイアウトと統計収集の恩恵を受ける既知のスキーマを持つデータに引き続きメリットがあります。
詳細については、次の記事を参照してください。
JSON 文字列を使用する
標準の JSON 形式を使用して 1 つの文字列列にデータを格納し、 :
表記を使用して JSON のフィールドをクエリできます。
多くのシステムは、文字列またはバイトエンコードされた JSON レコードとしてレコードを出力します。 これらのレコードを文字列として取り込んで保存すると、処理オーバーヘッドが非常に少なくなります。 また、 to_json
関数を使用して、データの任意の構造体を JSON 文字列に変換することもできます。
データを JSON 文字列として保存することを選択する場合は、次の長所と短所を考慮してください。
- すべての値は、型情報のない文字列として格納されます。
- JSON は、テキストを使用して表現できるすべてのデータ型をサポートします。
- JSON は、任意の長さの文字列をサポートします。
- 1 つの JSON データ列で表現できるフィールドの数に制限はありません。
- データは、テーブルに書き込む前に前処理を行う必要はありません。
- ダウンストリーム ワークロードのデータに存在する型の問題を解決できます。
- JSON は、クエリごとに文字列全体を解析する必要があるため、読み取り時のパフォーマンスが最も悪くなります。
JSON 文字列は、生データをレイクハウスのテーブルに取り込むための優れた柔軟性と実装しやすいソリューションを提供します。 多くのアプリケーションで JSON 文字列を使用することを選択できますが、ワークロードの最も重要な結果が、ダウンストリーム処理のためにデータソースの完全かつ正確な表現を保存することである場合に特に便利です。 使用例には、次のようなものがあります。
- Kafka などのキュー サービスからストリーミング データを取り込む。
- 応答 REST API クエリの記録。
- チームが制御していないアップストリームデータソースからの生レコードを保存する。
インジェストロジックが柔軟であると仮定すると、データを JSON 文字列として格納すると、新しいフィールド、データ構造の変更、またはデータソースの型の変更が発生した場合でも回復力があるはずです。 これらの変更によりダウンストリームのワークロードが失敗する可能性がありますが、テーブルにはソースデータの完全な履歴が含まれているため、データソースに戻ることなく問題を修復できます。
構造体を使用する
半構造化データを構造体で保存し、データソースのネスト構造を維持しながら、カラムのすべてのネイティブ機能を有効にすることができます。
Delta Lake は、構造体として格納されたデータを他の列と同じように扱うため、構造体や列との機能的な違いはありません。 Delta Lake で使用される Parquet データ ファイルは、構造体内の各フィールドの列を作成します。 構造体フィールドは、クラスタリング列またはパーティション分割列として使用し、データスキップのために構造体の統計を収集できます。
構造体は、すべてのデータ スキップ最適化をサポートし、個々のフィールドを列として保存するため、一般に読み取り時に最高のパフォーマンスを提供します。 存在する列の数が数百になると、パフォーマンスが低下し始める可能性があります。
構造体の各フィールドにはデータ型があり、これは列と同じように書き込みに適用されます。 そのため、構造体にはデータの完全な前処理が必要です。 これは、検証されたデータのみをテーブルにコミットする場合に便利ですが、アップストリームシステムからの不正な形式のレコードを処理するときには、データがドロップされたり、ジョブが失敗したりする可能性があります。
構造体は、データ型の進化や新しいフィールドの追加など、スキーマの進化において JSON ストリームよりも柔軟性が低くなります。
マップと配列を使用する
マップと配列の組み合わせを使用して、半構造化データ形式を Delta Lake でネイティブにレプリケートできます。 これらのタイプで定義されたフィールドでは統計を収集できませんが、約 500 のフィールドを持つ半構造化データセットの読み取りと書き込みの両方でバランスの取れたパフォーマンスを提供します。
マップのキーと値の両方が型指定されるため、データは前処理され、書き込み時にスキーマが適用されます。
クエリを高速化するために、Databricks では、データのフィルター処理によく使用されるフィールドを個別の列として格納することをお勧めします。
データをフラット化する必要がありますか?
JSON またはマップを使用してデータを保存する場合は、クエリのフィルタリングに頻繁に使用されるフィールドを列として保存することを検討してください。 統計の収集、パーティション分割、クラスタリングは、JSON 文字列またはマップ内のフィールドでは使用できません。 構造体として格納されたデータに対しては、これを行う必要はありません。
ネストされたデータを操作するための構文
ネストされたデータの操作に関する情報については、次のリソースを参照してください。