PolarDBは、結合条件のプッシュダウン機能をサポートしています。 外部結合条件が派生テーブルにプッシュダウンされた後、実行プランはインデックスをより効率的に使用できます。 これにより、複雑なクエリのパフォーマンスが大幅に向上します。
前提条件
クラスターは、リビジョンバージョンが8.0.2.2.10以降のPolarDB for MySQL 8.0を実行します。
背景
派生テーブル (またはインラインビュー) は、複雑な分析クエリで広く使用され、SQLステートメントの構築を簡素化し、クエリのセマンティクスを簡単に記述します。 ネイティブMySQLで、派生テーブルを外部クエリにマージできない場合 (たとえば、GROUP BYや集計関数などの操作が含まれている場合) 、具体化を使用して派生テーブルを実行する必要があります。 SQL文に膨大なデータが含まれる場合 (たとえば、大量のテーブルデータをスキャンする必要がある場合) 、実行効率が過度に低くなる可能性があります。 外部結合条件が派生テーブルにプッシュダウンされた後、実行プランはインデックスをより効率的に使用できます。 これにより、複雑なクエリのパフォーマンスが大幅に向上します。
シナリオ
複雑なクエリでは、派生テーブルと外部テーブルはネストされたループで結合されます。 結合された列は、派生テーブルの内側のレイヤーにあります。 したがって、インデックスを使用して、内部テーブルの具体化を高速化できます。 結合条件が押し下げられた後に、大量のデータが内部層でフィルタリングされ得ることを保証するために、正確な統計が必要とされる。
結合条件がプッシュダウンされた後、インデックスを効果的に使用でき、大量のデータが除外されると、より効率的な実行プランが生成されます。 結合条件プッシュダウン機能は、外部結合条件をプッシュダウンするかどうかをインテリジェントに決定するために、オプティマイザのコスト計算能力に依存する。
使用法
loose_polar_optimizer_switch
パラメーターを使用して結合条件pushdownを有効にし、loose_join_predicate_pushdown_opt_mode
パラメーターを使用して結合条件pushdownを有効にするノードを指定できます。 パラメーターの設定方法については、「クラスターおよびノードパラメーターの設定」をご参照ください。
パラメーター | レベル | 説明 |
loose_polar_optimizer_switch | グローバルとセッション | 結合条件のプッシュダウンを有効にするかどうかを指定します。 有効な値:
|
loose_join_predicate_pushdown_opt_mode | グローバル | 結合条件のプッシュダウンを有効にするノードを指定します。 有効な値:
|
例
元のクエリ
元のクエリでは、os
派生テーブルは完全に具体化されている必要があり、高い選択率を提供できるフィルタ条件はありません。 そのため、os
派生テーブルを具体化するのに長い時間を要する。 このクエリの完了には約65秒かかります。
SELECT *
から (
SELECT *
sample_table.tb_orderから
WHERE create_date >= DATE_SUB(CAST('2022-12-05 15:12:05 'AS datetime) 、インターバル5分)
AND product_type IN (2, 4)
) o
左の参加 (
SELECT *
FROM sample_table.tb_order_detailed
WHERE update_time >= DATE_SUB('2022-12-05 15:12:05 '、インターバル50分)
) od
ON o.order_id = od.order_id
左の参加 (
SELECT t.*, row_number() OVER (PARTITION BY detail_id ORDER BY update_date DESC) AS rn
sample_table.tb_order_sku tから
WHERE update_date >= DATE_SUB('2022-12-05 15:12:05 '、インターバル50分)
そして合体 (product_type、'0') <> '5'
) os
ON od.id = os.de tail_id;
最適化されたクエリ
od
テーブルとos
テーブルの間の結合条件od.id = os.de tail_id
は、os
テーブルにプッシュダウンされます。 この場合、os
テーブルはdetail_id
インデックスを使用して大量のデータを除外し、実行効率を向上させることができます。 クエリの完了には約0.5秒かかります。
SELECT *
から (
SELECT *
db_order.tb_orderから
WHERE create_date >= DATE_SUB(CAST('2022-12-05 15:12:05 'AS datetime) 、インターバル5分)
AND product_type IN (2, 4)
) o
左の参加 (
SELECT *
FROM db_order.tb_order_detailed
WHERE update_time >= DATE_SUB('2022-12-05 15:12:05 '、インターバル50分)
) od
ON o.order_id = od.order_id
左側に参加 (()
SELECT t.*, row_number() OVER (PARTITION BY detail_id ORDER BY update_date DESC) AS rn
db_order.tb_order_sku tから
WHERE update_date >= DATE_SUB('2022-12-05 15:12:05 '、インターバル50分)
そして合体 (product_type、'0') <> '5'
AND od.id = detail_id
) os;