次のようなクエリが表示されます。
select *
from a, b
where a.val = b.val
and a.val = 1
Oracleオプティマイザは推移閉包プロパティを使用し、2つの述語a.val = b.val
とa.val = 1
を組み合わせて別の述語b.val = 1
を導き出すことができます。それは実行プランの述語情報で見ることができます:
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 600 | 3600 | 5 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 600 | 3600 | 5 (0)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| B | 20 | 60 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | VAL_I | 20 | | 1 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL | A | 30 | 90 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."VAL"="B"."VAL")
3 - access("B"."VAL"=1)
4 - filter("A"."VAL"=1)
ただし、別の環境(同じOracleバージョン-12.1.0.2)では同じ動作を再現できません。
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 360 | 2160 | 6 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 360 | 2160 | 6 (0)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 30 | 90 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| B | 1000 | 3000 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."VAL"="B"."VAL")
2 - filter("A"."VAL"=1)
述語がないため、インデックスは使用されません。報告されたカーディナリティーも正しくありません。
おそらくオプティマイザパラメータを介して、この動作を制御する方法はありますか?
パラメータ_optimizer_filter_pushdown
がfalse
に設定されていることがわかりました。これは、_optimizer_generate_transitive_pred
と同様に、遷移述語の生成にも影響します Balazs Pappが提案しました。 trueに設定すると、問題はなくなります。
alter session set "_optimizer_filter_pushdown"=true;
create table a(val number);
create table b(val number);
explain plan for select * from a, b where a.val = b.val and a.val = 1;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 652036164
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 4 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 26 | 4 (0)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 1 | 13 | 2 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| B | 1 | 13 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."VAL"="B"."VAL")
2 - filter("A"."VAL"=1)
3 - filter("B"."VAL"=1)
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
そしてパラメータ:
SQL> alter session set "_optimizer_generate_transitive_pred"=false;
Session altered.
SQL> explain plan for select * from a, b where a.val = b.val and a.val = 1;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 652036164
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 4 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 26 | 4 (0)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 1 | 13 | 2 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| B | 1 | 13 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."VAL"="B"."VAL")
2 - filter("A"."VAL"=1)
Note
-----
- dynamic statistics used: dynamic sampling (level=2)