データ接続と統合パイプラインの最適化データセットプロジェクション概要

注: 以下の翻訳の正確性は検証されていません。AIPを利用して英語版の原文から機械的に翻訳されたものです。

データセットプロジェクション

データセットプロジェクションは、幅広い種類のクエリのパフォーマンスを向上させることができます。複数のクエリパターン(たとえば、2つの異なる列での絞り込み)に合わせて最適化したいデータセットがある場合は、そのデータセットへのプロジェクションの追加を検討してください。プロジェクションのユースケースの具体例を以下に示します。

各プロジェクションは通常、単一のクエリパターンをサポートし、特定の列でのフィルターまたは特定の列での結合の改善に重点を置きます。データセットには複数のプロジェクションを追加でき、プロジェクションではすべての列のデータ型がサポートされます。また、スナップショットとして、またはインクリメンタルにビルドされたデータセットにもプロジェクションを追加できます。プロジェクションの管理には Noho サービスが使用され、プロジェクションを設定する際にデータセットスキーマで参照されます。

プロジェクションにはいくつかの制限があります。

  • プロジェクションは、追加専用のデータセットにのみ追加できます。追加専用のデータセットでは、データセットに行を追加することしかできず、ファイルやトランザクションを手動で削除することはできません。具体的には、追加専用のデータセットで実行できるトランザクションは、データセットに行を追加する APPEND、SNAPSHOT、UPDATE トランザクションのみです。プロジェクションシステムは、この要件に違反するデータセットを自動的に特定し、そのデータセットのプロジェクションを無効にしますが、ユーザーとしてもこのような状況を避けるようにしてください。
  • プロジェクションはスキーマの変更をサポートしていません。列の追加のように、インクリメンタル処理との整合性が保たれる操作であってもサポートされません。

以下のユースケースの例を確認して、プロジェクションが用途に適しているかを判断してください。まずはプロジェクションを設定する方法を学んではじめましょう。

ユースケース

多くの種類のクエリで、プロジェクションを活用できます。以下の例では、次の内容を示します。

列のリストで絞り込む

順序付きの列リストに対して、そのリストの任意の接頭辞に対するフィルターを最適化します。プロジェクションで高速化できるのは、列と特定の値を比較するフィルターのみです。また、文字列列に対するフィルターは、必ず大文字と小文字を区別する必要があります。

たとえば、順序付きの列リスト ["x", "y", "z"] に対するフィルター用に最適化されたプロジェクションがあるとします。 このプロジェクションは、次の種類のクエリを高速化します。

  • SELECT * FROM dataset WHERE x = 5 AND y = 10 AND z = '15'
  • SELECT * FROM dataset WHERE x = 5 AND y = 10
  • SELECT * FROM dataset WHERE x = 5 AND q = 3
    • この例の q = 3 のように、設定済みのリストに含まれないほかの列に追加のフィルターがある場合、Spark は、データソースに「プッシュ」できるフィルター条件(この場合は x = 5)を自動的に分離しようとし、その後にほかの条件を適用します。

ただし、次の種類のクエリは最適化されません。

  • SELECT * FROM dataset WHERE abs(x) == 10
    • abs(x) == 10 は、列と特定の値を比較していません。
  • SELECT * FROM dataset WHERE x % 100 == 10
    • x % 100 == 10 は、列と特定の値を比較していません。
  • SELECT * FROM dataset WHERE y = 10
    • ["y"] は ["x", "y", "z"] の接頭辞ではありません。
  • SELECT * FROM dataset WHERE z = '15'
    • ["z"] は ["x", "y", "z"] の接頭辞ではありません。
  • SELECT * FROM dataset WHERE x = 5 OR q = 3
    • Spark は x = 5 フィルターをデータソースに「プッシュ」できません。プッシュすると、x = 5 が false でも q = 3 が true である行を取りこぼすためです。

範囲クエリ

プロジェクションでは、オプションでフィルター列に対する範囲クエリも高速化できます。たとえば、次のようなクエリです。

  • SELECT * FROM dataset WHERE x > 5 AND x < 10
  • SELECT * FROM dataset WHERE s LIKE 'SOME_PREFIX%'

制限事項

  • 非プリミティブ型(たとえば配列)の列を含み、かつフィルター列に対する範囲クエリもサポートする プロジェクションは作成できません。

列の集合で結合する

順序のない列の集合とバケット数に対して、その集合とバケット数に完全一致する結合のみを最適化します。

たとえば、{"x", "y"} に対する結合用に最適化されたプロジェクションは、次の種類のクエリを最適化します。

  • SELECT * FROM dataset1 INNER JOIN dataset2 ON dataset1.x = dataset2.x AND dataset1.y = dataset2.y

ただし、次のクエリは最適化されません。

  • SELECT * FROM dataset1 INNER JOIN dataset2 ON dataset1.x = dataset2.x

プロジェクションがあるデータセットとないデータセットを結合する

Foundry では、大規模なデータセットの結合で通常ソートマージ結合が実行されます。これは、それぞれのデータセットを 結合キーに従ってパーティション分割し、各パーティションをそのキーで並べ替えてから、同じ キーを持つ(並べ替え済みの)パーティションをマージする処理です。

  • 一般的には、両方のデータセットのシャッフルと並べ替えが行われます。
  • 一方のデータセットに、結合列での結合用に最適化されたプロジェクションがある場合、そのデータセットはシャッフルも並べ替えもされませんが、もう一方のデータセットでは両方が行われます。
  • 両方のデータセットに、結合列での結合用に最適化されたプロジェクションがあり、かつ同じバケット数を使用している場合、どちらのデータセットもシャッフルも並べ替えもされません。これにより、パフォーマンスが大幅に向上する可能性があります。結合用に最適化されたプロジェクションを持つデータセットと、明示的にバケット分割された(プロジェクションのない)データセットを結合する場合も同様ですが、この場合もバケット数と結合列が完全に一致している必要があります。

Foundry でプロジェクションを利用するコンシューマーのほとんどは、ソートマージ結合の実行時に、プロジェクションがすでに並べ替え済みであることをデフォルトでは活用しません。そのため、Spark のクエリプランに並べ替えが表示される場合があります。トランスフォームでは、Spark プロファイル BUCKET_SORTED_SCAN_ENABLED を使用して、プロジェクションが並べ替え済みであることに基づいて Spark の動作を変更できます。ただし、これによって必ずパフォーマンスが向上するとは限らず、実際にはパフォーマンスが低下することもあります。

事前に指定した列の集合で集計する

Foundry では、集計の際に通常、集計キーに従ってデータセットにシャッフル交換を実行します(つまり、データセットをパーティション分割します)。ハッシュバケット分割されたプロジェクションから読み取る場合(結合用に最適化されたプロジェクションはすべて該当しますが、フィルター用に最適化されたプロジェクションは該当しない場合があります)、コンシューマーはこのシャッフルを回避でき、集計時のパフォーマンスが大幅に向上する可能性があります。追加のみでインクリメンタルに更新されるデータセットに対する主キーのデータが満たすべき条件のチェックは、(主キー列に対する)プロジェクションが特に有効なケースです。これは、プロジェクションによってコンパクションが実行されることに加え、データが満たすべき条件を評価するための集計で、プロジェクションのハッシュバケット分割を活用できるためです。

インクリメンタルパイプラインから読み取る

インクリメンタルパイプラインでは、ファイル数が非常に多くなり、それに伴って読み取りパフォーマンスが低下する可能性があります。たとえば、5分ごとに10個のパーティションを書き込むパイプラインでは、年間100万個を超えるファイルが書き込まれます。入力パーティションのリストを作成するだけでも負荷がかかるなど、さまざまな理由から、これらのファイルの読み取りは困難です。

プロジェクションを使用すると、このようなインクリメンタルパイプラインを透過的にコンパクションできます。フィルターまたは結合用に最適化されたプロジェクションを設定するだけで、読み取り時にそのプロジェクションが使用されます。インクリメンタルパイプラインでのプロジェクションの使用について詳しくはこちら。

プロジェクションが正規データセットの最新状態に完全には追従していない場合でも、コンシューマーはプロジェクションのフィルターまたは結合の最適化を活用できます。ただし、プロジェクションが最後にビルドされた時点での最新トランザクションから、正規データセットの現在の最新トランザクションまでの間に、正規データセットで SNAPSHOT または DELETE トランザクション(あるいは既存のファイルを変更する UPDATE トランザクション)が発生していないことが条件です。

アップロードされたデータにクエリを実行する

CSV はデータへのクエリ実行には非効率なファイル形式ですが、Foundry にアップロードされるデータ(ファイルシステムソースから Data Connection を介して取り込まれるデータや、手動でアップロードされるデータなど)は、最初は CSV 形式であることが一般的です。トランスフォームジョブの作成は、これらの CSV を Parquet などのより効率的な形式に変換する方法の1つです。別の方法として、プロジェクションを追加することもできます。この場合、データセットには元の CSV ファイルが保持されたまま、読み取り操作では最適化されたプロジェクションが使用され、パフォーマンスが向上します。