半構造化データをモデル化する
この記事では、組織でのデータの使用方法に応じて、半構造化データの格納に推奨されるパターンを示します。 Azure Databricks には、半構造化形式の入れ子になった複合データを操作するための関数、ネイティブ データ型、クエリ構文が用意されています。
次の考慮事項は、使用する必要があるパターンに影響します。
- データ ソースのフィールドまたは型は頻繁に変更されますか?
- データ ソースに含まれる一意のフィールドの数は全部でいくつですか?
- 書き込みまたは読み取りのためにワークロードを最適化する必要がありますか?
Databricks では、下流のクエリのために Delta テーブルとしてデータを格納することをお勧めします。
バリアントの使用
Databricks Runtime 15.3 以降では、読み書きで JSON 文字列を上回る最適化されたエンコードを使用して半構造化 JSON データを格納するために VARIANT
型を使用できます。
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 文字列またはマップ内のフィールドでは使用できません。 構造体として格納されるデータに対してこれを行う必要はありません。
入れ子になったデータを操作するための構文
入れ子になったデータの操作については、次のリソースを確認してください。