SUBPLAN FILTER 演算子は、ドライバー式の中のサブクエリの実行を制御します。
OceanBaseデータベースは NESTED LOOP アルゴリズムを用いて SUBPLAN FILTER 演算子を実行します。実行時には、まず左側から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を実行し、条件に合致するデータ行を出力します。