AlexFF__| |
В запросе среди условий есть следующая строка
and ID = :A1 при заменен ее на
and ID = NVL(:A1, :A2) оптимизатор выдает план на 2 подзапроса с последующей конкатенацией. Почему??? |
Наверное, все-таки неправильное условие. Должно быть что-то вроде ID=NVL(:A1, ID)
В этом случае получается две ветки, каждая из которых идет по оптимальному пути: индекс, если A1 NOT NULL и полный просмотр в противном случае.
FILTER в начале каждой ветки содержат взаимоисключающие условия, что гарантирует выполнение только одной ветки
tst> create table t1(id primary key, val) as
2 select rownum id, to_char(rownum) val from dual connect by level <= 10000;
Table created.
tst> exec dbms_stats.gather_table_stats(user, 'T1', cascade=>true);
PL/SQL procedure successfully completed.
tst> var a1 number
tst> var a2 number
tst> set autotrace traceonly explain
tst> select * from t1 where id=nvl(:a1, :a2);
Execution Plan
----------------------------------------------------------
Plan hash value: 2696841811
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 8 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 8 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | SYS_C0018376 | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=TO_NUMBER(NVL(:A1,:A2)))
tst> select * from t1 where id=nvl(:a1, id);
Execution Plan
----------------------------------------------------------
Plan hash value: 3283325471
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10001 | 80008 | 10 (0)| 00:00:01 |
| 1 | CONCATENATION | | | | | |
|* 2 | FILTER | | | | | |
|* 3 | TABLE ACCESS FULL | T1 | 10000 | 80000 | 8 (0)| 00:00:01 |
|* 4 | FILTER | | | | | |
| 5 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 8 | 2 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | SYS_C0018376 | 1 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(:A1 IS NULL)
3 - filter("ID" IS NOT NULL)
4 - filter(:A1 IS NOT NULL)
6 - access("ID"=:A1)