半構造化データのモデル化

この記事では、組織でのデータの使用方法に応じて、半構造化データを格納するためのパターンを推奨します。 Databricks は、半構造化データ、ネストされたデータ、複雑なデータを処理するための関数、ネイティブ データ型、クエリ構文を提供します。

次の考慮事項は、使用するパターンに影響します。

  • データソース内のフィールドまたはタイプは頻繁に変更されますか?

  • データソースには合計でいくつの固有フィールドが含まれていますか?

  • 書き込みまたは読み取りのワークロードを最適化する必要がありますか?

Databricks では、ダウンストリーム クエリ用にデータを Delta テーブルとして保存することを推奨しています。

バリアントを使用する

Databricks Runtime 15.3 以降では、 VARIANT型を使用して、読み取りと書き込みで JSON 文字列よりも優れたパフォーマンスを発揮する最適化されたエンコードを使用して、半構造化 JSON データを格納できます。

VARIANT型には JSON 文字列と同様の用途があります。 一部のワークロードでは、特に、最適化されたデータ レイアウトと統計収集の恩恵を受ける既知のスキーマを持つデータに対して、構造体、マップ、配列を使用することでメリットが得られます。

詳細については、次の記事を参照してください。

JSON使用する

標準の JSON 形式を使用して単一の文字列列にデータを保存し、 :表記を使用して JSON 内のフィールドをクエリできます。

多くのシステムは、レコードを文字列またはバイトエンコードされた JSON レコードとして出力します。 これらのレコードを文字列として取り込んで保存すると、処理オーバーヘッドが非常に低くなります。 to_json関数を使用して、任意のデータ構造を JSON 文字列に変換することもできます。

データを JSON 文字列として保存することを選択する場合は、次の長所と短所を考慮してください。

  • すべての値は型情報のない文字列として保存されます。

  • JSON は、テキストを使用して表現できるすべてのデータ型をサポートします。

  • JSON は任意の長さの文字列をサポートします。

  • 単一の JSON データ列で表現できるフィールドの数に制限はありません。

  • データは、テーブルに書き込む前に前処理を行う必要はありません。

  • ダウンストリーム ワークロードのデータに存在する型の問題を解決できます。

  • JSON では、クエリごとに文字列全体を解析する必要があるため、読み取りのパフォーマンスが最も悪くなります。

JSON 文字列は、レイクハウス テーブルに生データを取り込むための優れた柔軟性と実装の容易さを備えたソリューションを提供します。 多くのアプリケーションでJSON文字列を使用することを選択できますが、ワークロードの最も重要な結果が、下流の処理のためにデータソースの完全かつ正確な表現を保存することである場合に特に役立ちます。 たとえば、次のようなユースケースがあります。

  • Kafka などのキュー サービスからストリーミング データを取り込みます。

  • REST API クエリの応答を記録します。

  • チームが管理していない上流のデータソースからの生のレコードを保存します。

取り込みロジックが柔軟であると仮定すると、新しいフィールド、データ構造の変更、またはデータソースの型の変更が発生した場合でも、データをJSON文字列として保存すると回復力が増すはずです。 これらの変更によりダウンストリームのワークロードが失敗する可能性がありますが、テーブルにはソース データの完全な履歴が含まれているため、データソースに戻らなくても問題を修正できます。

構造体を使用する

構造体を使用して半構造化データを保存し、データソースのネストされた構造を維持しながら、列のすべてのネイティブ機能を有効にすることができます。

Delta Lake は、構造体として保存されたデータを他の列と同じように扱います。つまり、構造体と列の間に機能上の違いはありません。 Delta Lake で使用される Parquet データ ファイルは、構造体内の各フィールドに列を作成します。 構造体フィールドをクラスタリング列またはパーティション列として使用し、データ スキップの構造体に関する統計を収集できます。

構造体は、すべてのデータスキップの最適化をサポートし、個々のフィールドを列として格納するため、通常、読み取り時に最高のパフォーマンスを提供します。 存在する列の数が数百に達すると、パフォーマンスが低下し始める可能性があります。

構造体の各フィールドにはデータ型があり、列と同じように書き込み時に適用されます。 そのため、構造体にはデータの完全な前処理が必要です。 これは、検証されたデータのみをテーブルにコミットしたい場合には便利ですが、上流システムからの不正なレコードを処理するときに、データが削除されたり、ジョブが失敗したりする可能性があります。

構造体は、データ型の進化や新しいフィールドの追加など、進化に関してJSONストリームほど柔軟性がありません。

マップと配列を使用する

マップと配列の組み合わせを使用して、半構造化データ形式を Delta Lake でネイティブに複製できます。 これらのタイプで定義されたフィールドでは統計を収集できませんが、約 500 個のフィールドを持つ半構造化データセットの読み取りと書き込みの両方でバランスの取れたパフォーマンスが提供されます。

マップのキーと値の両方が型指定されるため、データは前処理され、スキーマは書き込みに適用されます。

クエリを高速化するために、Databricks では、データをフィルター処理するためによく使用されるフィールドを個別の列として保存することをお勧めします。

データをフラット化する必要がありますか?

JSON またはマップを使用してデータを保存する場合は、クエリのフィルタリングに頻繁に使用されるフィールドを列として保存することを検討してください。 統計収集、パーティション分割、クラスタリングは、JSON 文字列またはマップ内のフィールドでは使用できません。 構造体として格納されているデータに対しては、これを行う必要はありません。

ネストされたデータを操作するための構文

ネストされたデータの操作に関する情報については、次のリソースを参照してください。