SUBPLAN FILTER 演算子は、ドライバー式のサブクエリの実行を制御します。
OceanBaseデータベースでは、SUBPLAN FILTER 演算子は NESTED LOOP アルゴリズムによって実行されます。実行時には、左側から1行のデータを取得し、その後右側のサブプランが実行されます。SUBPLAN FILTER 演算子は、非関連サブクエリと関連サブクエリの両方を駆動して計算を行うことができ、その実行方法はそれぞれ異なります。
非関連サブクエリの計算をドライバーが実行する
例1:SUBPLAN FILTER演算子が非関連サブクエリの計算を実行する
obclient> CREATE TABLE t1(c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> CREATE TABLE t2(c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> EXPLAIN SELECT /*+NO_REWRITE*/c1 FROM t1 WHERE c2 > (SELECT MAX(c2) FROM t2);
+---------------------------------------------------------------------------------------------------+
| Query Plan |
+---------------------------------------------------------------------------------------------------+
| =================================================== |
| |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------- |
| |0 |SUBPLAN FILTER | |1 |5 | |
| |1 |├─TABLE FULL SCAN |t1 |1 |3 | |
| |2 |└─SCALAR GROUP BY | |1 |3 | |
| |3 | └─TABLE FULL SCAN|t2 |1 |3 | |
| =================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([t1.c1]), filter(nil), rowset=16 |
| exec_params_(nil), onetime_exprs_([subquery(1)(:0)]), init_plan_idxs_(nil), use_batch=false |
| 1 - output([t1.c1]), filter([t1.c2 > :0]), rowset=16 |
| access([t1.c2], [t1.c1]), partitions(p0) |
| is_index_back=false, is_global_index=false, filter_before_indexback[false], |
| range_key([t1.__pk_increment]), range(MIN ; MAX)always true |
| 2 - output([T_FUN_MAX(T_FUN_MAX(t2.c2))]), filter(nil), rowset=16 |
| group(nil), agg_func([T_FUN_MAX(T_FUN_MAX(t2.c2))]) |
| 3 - output([T_FUN_MAX(t2.c2)]), filter(nil), rowset=16 |
| access([t2.c2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t2.__pk_increment]), range(MIN ; MAX)always true, |
| pushdown_aggregation([T_FUN_MAX(t2.c2)]) |
+---------------------------------------------------------------------------------------------------+
23 rows in set
上記の例では、実行計画表示において、演算子番号0のSUBPLAN FILTERが右側のSCALAR GROUP BYサブプランの実行をドライバーとして機能し、outputs & filters詳細列にはSUBPLAN FILTER演算子の出力情報が以下のように詳細に示されています:
| 情報名 | 意味 |
|---|---|
| output | この演算子が出力する列。 |
| filter | この演算子上のフィルタ条件。例の SUBPLAN FILTER 演算子では filter が設定されていないため、nil となります。 |
| exec_params_ | 右側のサブプランが左側のサブプランに依存するパラメータであり、実行時には SUBPLAN FILTER が左側のサブプランから取得し、右側のサブプランへ渡して実行します。例の SUBPLAN FILTER 演算子が非関連サブクエリを駆動する場合、このパラメータは関与しないため、nil となります。 |
| onetime_exprs_ | プラン内で一度だけ計算される式です。右側のサブプランが非関連サブクエリの場合、繰り返し実行される結果は毎回同じであるため、一度実行した後、パラメータセットに保存されます。SUBPLAN FILTER を実行するたびに、パラメータセットから直接右側のサブプランの実行結果を取得できます。パラメータ subquery(1) は、SUBPLAN FILTER の右側の最初のサブプランが onetime expr_ であることを示します。 |
| init_plan_idxs_ | この演算子内で一度だけ実行されるサブプラン。 onetime_exprs_ との違いは、init_plan_ が複数行複数列を返すのに対し、onetime_expr_ は単一行単一列を返す点です。例のSQLクエリではこの項目が設定されていないため、nil となります。 |
SUBPLAN FILTER演算子が非関連サブクエリの計算をドライバーとして実行する一般的な実行プロセスは以下の通りです:
SUBPLAN FILTER起動時にonetime_exprs_を実行します。パラメータから右側の非関連サブクエリの結果を取得し、
filterを左側の計画にプッシュダウンして左側のクエリを実行します。左側のクエリの行を出力します。
ドライバー関連のサブクエリ計算
例2:SUBPLAN FILTER演算子が関連するサブクエリの計算をドライブする
obclient> EXPLAIN SELECT /*+NO_REWRITE*/c1 FROM t1 WHERE c2 > (SELECT MAX(c2) FROM t2 WHERE t1.c1=t2.c1);
+---------------------------------------------------------------------------------------------+
| Query Plan |
+---------------------------------------------------------------------------------------------+
| =================================================== |
| |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------- |
| |0 |SUBPLAN FILTER | |1 |5 | |
| |1 |├─TABLE FULL SCAN |t1 |1 |3 | |
| |2 |└─SCALAR GROUP BY | |1 |3 | |
| |3 | └─TABLE FULL SCAN|t2 |1 |3 | |
| =================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([t1.c1]), filter([t1.c2 > subquery(1)]), rowset=16 |
| exec_params_([t1.c1(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false |
| 1 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 |
| access([t1.c1], [t1.c2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t1.__pk_increment]), range(MIN ; MAX)always true |
| 2 - output([T_FUN_MAX(T_FUN_MAX(t2.c2))]), filter(nil), rowset=16 |
| group(nil), agg_func([T_FUN_MAX(T_FUN_MAX(t2.c2))]) |
| 3 - output([T_FUN_MAX(t2.c2)]), filter([:0 = t2.c1]), rowset=16 |
| access([t2.c1], [t2.c2]), partitions(p0) |
| is_index_back=false, is_global_index=false, filter_before_indexback[false], |
| range_key([t2.__pk_increment]), range(MIN ; MAX)always true, |
| pushdown_aggregation([T_FUN_MAX(t2.c2)]) |
+---------------------------------------------------------------------------------------------+
23 rows in set
上記の例では、実行計画表示において0番目の演算子SUBPLAN FILTERが右側のSCALAR GROUP BYサブプランの実行をドライブし、outputs & filters詳細列にはSUBPLAN FILTER演算子の出力情報が以下のように詳細に示されています:
| 情報名 | 意味 |
|---|---|
| output | この演算子が出力する列。 |
| filter | この演算子におけるフィルタ条件。例えば、例2のSQLクエリのフィルタ条件は t1.c2 > subquery(1) です。 |
| exec_params_ | 右側のサブプランが左側のサブプランに依存するパラメータであり、実行時には SUBPLAN FILTER が左側のサブプランから取得し、右側のサブプランへと渡します。左側が1行のデータを出力した後にプッシュダウンする必要があるパラメータであり、非関連サブクエリでは一般的にプッシュダウンされるパラメータはありません。 |
| onetime_exprs_ | プラン内で一度だけ計算される式であり、右側のサブプランが非関連サブクエリの場合、繰り返し実行される結果は毎回同じであるため、一度実行した後はパラメータセットに保存されます。SUBPLAN FILTER を実行するたびに、パラメータセットから直接右側のサブプランの実行結果を取得できます。パラメータ subquery(1) は、SUBPLAN FILTER の右側の最初のサブプランが onetime expr_ であることを示します。例のSQLクエリではこの項目が設定されていないため、nil となります。 |
| init_plan_idxs_ | この演算子内で一度だけ実行されるサブプラン。 onetime_exprs_ との違いは、init_plan_ が複数行複数列を返すのに対し、onetime_expr_ は単一行単一列を返す点です。例のSQLクエリではこの項目が設定されていないため、nil となります。 |
SUBPLAN FILTER演算子が関連するサブクエリの計算をドライブする一般的な実行プロセスは以下のとおりです:
SUBPLAN FILTER起動時にonetime_exprs_を実行します。左側のクエリを実行し、1行出力した後、関連パラメータを計算して右側にプッシュダウンし、右側のサブクエリを実行します。
filterを実行し、条件に合致するデータ行を出力します。