план запроса

AlexFF__|
Дата: 23.11.2009 17:25:31
В запросе среди условий есть следующая строка
and ID = :A1
при заменен ее на
and ID = NVL(:A1, :A2)
оптимизатор выдает план на 2 подзапроса с последующей конкатенацией. Почему???
AlexFF__|
Дата: 23.11.2009 17:26:24
Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production
_Alex_SMIRNOV_
Дата: 23.11.2009 17:46:19
а планы и сами запросы увидеть можно?

на Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi, не делит на два... правда на такой версии как у вас нет возможности проверить...
AlexFF__|
Дата: 23.11.2009 17:53:03
_Alex_SMIRNOV_
а планы и сами запросы увидеть можно?

Проблема возникает при несложном соединении 3 таблиц, с 8-10 условиями и меняет план весьма хаотично в зависимости от других параметров. Я пока не смог сформировать пример, что-бы выложить для пробы.
Вячеслав Любомудров
Дата: 24.11.2009 02:25:59
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)
AlexFF__|
Дата: 24.11.2009 09:59:51
Вячеслав Любомудров,

Такое поведение оптимизатора понятно, однако в моем случае речь идет о двух bind-переменных и, соответственно, в плане обе ветки фильтров абсолютно одинаковые.