次の方法で共有


半構造化データをモデル化する

この記事では、組織でのデータの使用方法に応じて、半構造化データの格納に推奨されるパターンを示します。 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 文字列またはマップ内のフィールドでは使用できません。 構造体として格納されるデータに対してこれを行う必要はありません。

入れ子になったデータを操作するための構文

入れ子になったデータの操作については、次のリソースを確認してください。