このトピックでは、ApsaraDB for SelectDB で結合クエリを最適化する方法と、クエリ速度を向上させるための提案について説明します。
サポートされている物理演算子
ApsaraDB for SelectDB は、スタンドアロンエンジンでの結合クエリに対して、次の 2 つの物理結合演算子をサポートしています。
ハッシュ結合: 左テーブルと右テーブルの両方に存在する列に基づいて、右テーブルにハッシュテーブルを作成できます。その後、ApsaraDB for SelectDB はハッシュテーブルを使用して、左テーブルの結合計算をストリーミング方式で実行します。これは、等価条件を使用する結合クエリにのみ適用されます。
ネストループ結合: ApsaraDB for SelectDB は、2 つの for ループで結合計算を実行します。これは、非等価条件を使用する結合クエリに適用されます。たとえば、「>」や「<」などの演算子を使用して条件を設定してデータをクエリしたり、デカルト積を取得したりできます。この演算子は一般的な結合演算子ですが、パフォーマンスが低いという欠点があります。
シャッフル方法
ApsaraDB for SelectDB は、分散型の超並列プロセッサ(MPP)データベースです。 ApsaraDB for SelectDB テーブルで結合クエリを実行する場合は、データをシャッフルしてから、物理演算子を使用してデータを結合する必要があります。 ApsaraDB for SelectDB は、次の 4 つのシャッフル方法をサポートしています。このセクションでは、各シャッフル方法を使用してデータをシャッフルする方法の例も示します。
この例では、テーブル S とテーブル R が結合されています。 N は結合計算に関係するノードの数を示します。 T はテーブル内のデータレコードの数を示します。
ブロードキャスト結合
このシャッフル方法では、テーブル S の全データがテーブル R に送信される必要があります。結合計算に関係する各ノードには、テーブル S の全データ(
T(R))があります。これは一般的なシャッフル方法であり、ハッシュ結合演算子とネストループ結合演算子をサポートしています。このシャッフル方法のネットワークオーバーヘッドは、次の式を使用して計算されます:N × T(R)。テーブル S のデータは移動されず、テーブル R のデータはテーブル S のデータをスキャンするスキャンノードに送信されます。
シャッフル結合
ハッシュ結合演算子を使用して結合クエリを実行する場合、結合列に基づいてテーブル S とテーブル R のデータのハッシュ値を計算し、同じハッシュ値を分散システムの同じノードに送信できます。その後、分散システムを使用して結合クエリの速度を向上させることができます。このシャッフル方法のネットワークオーバーヘッドは、次の式に基づいて計算されます:
T(S) + T(R)。ただし、このシャッフル方法はハッシュ結合演算子のみをサポートしています。これは、データのハッシュ値が結合列に基づいて計算されるためです。テーブル S とテーブル R のデータは、パーティションに基づいて計算されます。結果は、異なるパーティションのノードに送信されます。
バケットシャッフル結合
ApsaraDB for SelectDB テーブルのデータは、データのハッシュ値に基づいてバケットに格納されます。これにより、テーブルのバケット列に基づいて結合するデータをシャッフルできます。たとえば、2 つのテーブル(テーブル S とテーブル R)を結合する場合、結合列はテーブル S のバケット列です。この場合、テーブル S のデータを移動する必要はなく、テーブル R のデータを移動することで結合計算を実行できます。
このシャッフル方法のネットワークオーバーヘッドは
T(R)です。これは、テーブル R のデータのみをシャッフルすることで結合計算を実行できることを示しています。バケットシャッフル結合方法の使用方法の詳細については、「バケットシャッフル結合」をご参照ください。テーブル S のデータは移動されず、パーティションに基づいて計算された結果に基づいて、テーブル R のデータがテーブル S のデータをスキャンするノードに送信されます。
コロケーション結合
相互に関連付けられている複数のテーブルの場合、テーブルの作成時に各テーブルのシャード数が同じである必要があります。これにより、クエリでのデータシャッフルをスキップし、直接結合計算を実行できます。これにより、クエリのパフォーマンスが向上します。コロケーション結合の詳細については、「コロケーション結合」をご参照ください。
データは事前にパーティション分割されています。ネットワークオーバーヘッドを考慮する必要はありません。オンプレミスコンピューターで直接結合計算を実行できます。
次の表に、4 つのシャッフル方法を示します。
シャッフル方法 | ネットワークオーバーヘッド | 物理演算子 | シナリオ |
ブロードキャスト | N × T(R) | ハッシュ結合またはネストループ結合 | 一般的なシナリオ |
シャッフル | T(S) + T(R) | ハッシュ結合 | 一般的なシナリオ |
バケットシャッフル | T(R) | ハッシュ結合 | 左テーブルの分散列が結合条件に存在し、左テーブルの単一パーティションのデータのみが結合クエリに使用されます。 |
コロケーション | 0 | ハッシュ結合 | 左テーブルの分散列が結合条件に存在し、左右のテーブルが同じコロケートグループに属しています。 |
上記のシャッフル方法は、柔軟性の高い順にソートされています。シャッフル方法のデータ分散の要件が高いほど、結合計算のパフォーマンスが高くなります。
ランタイムフィルター
ランタイムフィルターは、実行プラン中に動的に生成されます。結合クエリ中に、HashJoinNode は右テーブルをフィルター条件に変換し、フィルター条件を ScanNode にプッシュダウンします。その後、ScanNode は左テーブルのスキャン時にデータをフィルタリングおよびプルーニングします。この方法により、クエリ中のデータの読み取りと計算に必要な時間が大幅に短縮され、クエリのパフォーマンスが向上します。ランタイムフィルターの詳細については、「ランタイムフィルター」をご参照ください。
結合順序の変更
マルチテーブル結合のシナリオでは、結合の順序がクエリ全体のパフォーマンスに大きく影響します。
たとえば、次の図に示すように、3 つのテーブルが結合されています。 ScanA、ScanB、ScanC は、クエリ条件に基づいてスキャンされたテーブル A、テーブル B、テーブル C のデータを示します。
図の左側では、テーブル A とテーブル B のスキャンされたデータが結合され、2,000 行の中間結果が生成されます。次に、中間結果がテーブル C のスキャンされたデータと結合されます。
図の右側では、結合の順序が調整されています。テーブル A とテーブル C のスキャンされたデータが結合され、100 行の中間結果が生成されます。次に、中間結果がテーブル B のスキャンされたデータと結合されます。最終的な結合結果は同じですが、左側の図で生成された中間結果は右側の図の結果の 20 倍です。これにより、大きなパフォーマンスギャップが生じます。
ApsaraDB for SelectDB は、ルールベースの結合順序変更アルゴリズムをサポートしています。このアルゴリズムのロジックを以下に示します。
大きなテーブルを小さなテーブルと結合して、中間結果の量を減らします。
SELECT ステートメントの From の前に結合条件を持つテーブルを配置して、結合条件を持つテーブルのデータをフィルタリングします。
ハッシュ結合演算子は、ネストループ結合演算子よりも優先順位が高くなります。これは、ハッシュ結合演算子の実行速度がネストループ結合演算子の実行速度よりも大幅に速いためです。
結合クエリの最適化のソリューション
次のセクションでは、結合クエリを最適化するプロセスに含まれる手順について説明します。結合クエリを最適化するには、次の手順を実行します。
ApsaraDB for SelectDB が提供するプロファイルを使用して、クエリをトラブルシューティングします。プロファイルはクエリ全体でさまざまな情報を記録しており、パフォーマンスの最適化にとって非常に重要です。
ApsaraDB for SelectDB の結合メカニズムを理解し、クエリが遅い理由を分析します。
セッション変数を使用して結合操作の一部の動作を変更し、結合操作を最適化します。
クエリプランを確認して、最適化が有効になっているかどうかを確認します。
上記の 4 つの手順は、結合操作の標準的な最適化プロセスを示しています。上記の 4 つの手順を実行してもクエリ速度が向上しない場合は、データ結合の SQL ステートメントを書き直すか、データ分散を調整してデータが適切に分散されているかどうかを再確認する必要がある場合があります。この場合、クエリで使用されるすべての結合ステートメントを手動で変更する必要があります。ただし、この方法には比較的高コストがかかり、前の方法でクエリ速度が向上しない場合に詳細な分析に使用されます。
結合クエリの最適化に関する提案
次のセクションでは、ApsaraDB for SelectDB で結合クエリを最適化する方法に関する提案を示します。
結合クエリを実行する場合は、同じタイプの列を選択してデータキャストを削減するか、単純なタイプの列を選択して結合計算を高速化します。
キー列を選択してデータを結合します。詳細については、「ランタイムフィルター」をご参照ください。キー列のデータを結合することで、遅延マテリアライゼーションを効果的に実装できます。
コロケーションモードで大規模なテーブル間で結合を実行します。これは、大規模なテーブルを結合すると大量のネットワークオーバーヘッドが発生し、データシャッフルのコストが増加するためです。
ランタイムフィルターを適切に使用します。ランタイムフィルターは、結合で高いフィルター率が必要なシナリオに適しています。ただし、いくつかの副作用もあります。SQL ステートメントに含まれる列に基づいて、ランタイムフィルターを使用するかどうかを判断する必要があります。
複数のテーブルを結合する場合は、結合の合理性を判断する必要があります。左テーブルが大テーブルで、右テーブルが小テーブルであることを確認します。この場合、ハッシュ結合演算子はネストループ結合演算子よりもパフォーマンスが優れています。SQL ステートメントを書き直して、ヒントメソッドを使用して結合の順序を調整できます。