Стоимость запроса

S-q-l
Дата: 05.12.2007 23:00:34
Прошу прощения за то, что не смог найти в гугле нужную инфу.
Что означает, если стоимостной оптимизатор в плане выполнения пишет в верхней строке Cost = 100, а в строке пониже - Cost = 5000? Какова истинная стоимость запроса? Разве верхняя строка не итоговая?
Я и ёжик
Дата: 06.12.2007 10:47:46
Пример плана бы привели, что ли...
Наиболее вероятно, подзапрос в списке селект, который по сути является отдельным запросом и просто механически впихивается в план основному запроса, тогда в верхней строчке видна просто стоимость основного запроса.

explain plan for select a.*,
      ( SELECT COUNT(*) FROM SYS.col$ ) T
   from SYS.file$ a;
   
select * from table(dbms_xplan.display) ;
 
---------------------------------------------------------------------
| Id  | Operation             | Name   | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |    42 |  1680 |     2   (0)|
|   1 |  SORT AGGREGATE       |        |     1 |       |            |
|   2 |   INDEX FAST FULL SCAN| I_COL3 | 63282 |       |    39   (6)|
|   3 |  TABLE ACCESS FULL    | FILE$  |    42 |  1680 |     2   (0)|
---------------------------------------------------------------------

Может еще какой то bug или специальный случай, но не припоминаю таких.

Andrei Kiselev
--
The views expressed are my own and not necessarily those of my hedgehog
S-q-l
Дата: 06.12.2007 11:04:40
Спасибо!
Vladimir Sitnikov
Дата: 06.12.2007 11:08:19
Я и ёжик
Может еще какой то bug или специальный случай, но не припоминаю таких.
Пример одного из случаев:
optimizer_index_cost_adj == 2
Я и ёжик
Дата: 06.12.2007 11:41:20
Vladimir Sitnikov
Я и ёжик
Может еще какой то bug или специальный случай, но не припоминаю таких.
Пример одного из случаев:
optimizer_index_cost_adj == 2

Поподробнее пожалуйста.
Спасибо!
Vladimir Sitnikov
Дата: 06.12.2007 12:10:20
Я и ёжик
Поподробнее пожалуйста

Вроде, нехитрое дело. COST индексного доступа умножается на optimizer_index_cost_adj/100.
Из начальных условий, которые привёл автор: cost обращения к индексу -- 5000, cost с учётом cost_adj -- 100 находим: optimizer_index_cost_adj/100==100/5000 => optimizer_index_cost_adj=100*100/5000=2 :)

SQL> CREATE TABLE test AS SELECT lpad(dummy, 3000, dummy)||mod(level,50) dummy FROM dual CONNECT BY LEVEL<3000;
Table created.

SQL> CREATE INDEX test_ix ON test(dummy);
Index created.

SQL> EXEC dbms_stats.gather_table_stats(USER, 'test', estimate_percent=>100, cascade=>true);
PL/SQL procedure successfully completed.

SQL> alter session set optimizer_index_cost_adj=100;
Session altered.

SQL> EXPLAIN PLAN FOR SELECT * FROM test t WHERE dummy=:a;
Explained.

SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
| Id  | Operation            |  Name       | Rows  | Bytes | Cost  |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |    60 |   175K|    37 |
|*  1 |  INDEX RANGE SCAN    | TEST_IX     |    60 |   175K|    37 |
--------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T"."DUMMY"=:Z)

Note: cpu costing is off

14 rows selected.

SQL> ROLLBACK;
Rollback complete.

SQL> alter session set optimizer_index_cost_adj=50;
Session altered.

SQL> EXPLAIN PLAN FOR SELECT * FROM test t WHERE dummy=:a;

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
| Id  | Operation            |  Name       | Rows  | Bytes | Cost  |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |    60 |   175K|    19 | -- 19==37*50/100
|*  1 |  INDEX RANGE SCAN    | TEST_IX     |    60 |   175K|    37 |
--------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T"."DUMMY"=:Z)

Note: cpu costing is off

14 rows selected.

SQL> DROP TABLE test;
Table dropped.
Я и ёжик
Дата: 06.12.2007 12:30:16
Спасибо, понял!
Просто 10-ка в range scan показывает уже модифицированную стоимость.

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Prod
PL/SQL Release 10.2.0.2.0 - Production
CORE    10.2.0.2.0      Production
TNS for 32-bit Windows: Version 10.2.0.2.0 - Production
NLSRTL Version 10.2.0.2.0 - Production

SQL> CREATE TABLE test AS SELECT lpad(dummy, 3000, dummy)||mod(level,50) dummy FROM dual CONNECT BY LEVEL<3000;

Таблица создана.

SQL>  CREATE INDEX test_ix ON test(dummy);

Индекс создан.

SQL>  EXEC dbms_stats.gather_table_stats(USER, 'test', estimate_percent=>100, cascade=>true);

Процедура PL/SQL успешно завершена.

SQL> alter session set optimizer_index_cost_adj=100;

Сеанс изменен.

SQL> EXPLAIN PLAN FOR SELECT * FROM test t WHERE dummy=:a;

Объяснено.

SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1975725937

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         |    60 |   175K|    37   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| TEST_IX |    60 |   175K|    37   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - access("DUMMY"=:A)

Note
-----
   - 'PLAN_TABLE' is old version

17 строк выбрано.

SQL> rollback;

Откат завершен.

SQL> alter session set optimizer_index_cost_adj=50;

Сеанс изменен.

SQL> EXPLAIN PLAN FOR SELECT * FROM test t WHERE dummy=:a;

Объяснено.

SQL> 
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1975725937

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         |    60 |   175K|    19   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| TEST_IX |    60 |   175K|    19   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - access("DUMMY"=:A)

Note
-----
   - 'PLAN_TABLE' is old version

17 строк выбрано.

SQL> DROP TABLE test;

Таблица удалена.


Andrei Kiselev
--
The views expressed are my own and not necessarily those of my hedgehog
Vladimir Sitnikov
Дата: 06.12.2007 12:58:33
Я и ёжик
Просто 10-ка в range scan показывает уже модифицированную стоимость.
А для AND-EQUAL cost_adj учитывается 2 раза :)

CREATE TABLE test AS
 SELECT lpad(dummy, 1500, dummy)||mod(level,10) a,
        lpad(dummy, 1500, dummy)||mod(level,10) b
   FROM dual CONNECT BY LEVEL<3000;
                            
CREATE INDEX test_ixa ON test(a);
CREATE INDEX test_ixb ON test(b);  

exec dbms_stats.gather_table_stats(USER, 'test', estimate_percent=>100, cascade=>true);

SQL> alter session set optimizer_index_cost_adj=100;
Session altered.

SQL> rollback;
Rollback complete.

SQL> explain plan for
  2   select /*+ and_equal(t test_ixa test_ixb) */ rowid
  3     from test t
  4    where a=:1 and b=:2;
Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

Plan hash value: 2271363388

------------------------------------------------------------------------------
| Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |          |    30 | 90120 |   173   (0)| 00:00:03 |
|*  1 |  AND-EQUAL        |          |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| TEST_IXA |   300 |       |    79   (0)| 00:00:01 |
|*  3 |   INDEX RANGE SCAN| TEST_IXB |   300 |       |    79   (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("A"=:1 AND "B"=:2)
   2 - access("A"=:1)
   3 - access("B"=:2)

SQL> rollback;
Rollback complete.

SQL> alter session set optimizer_index_cost_adj=50;
Session altered.

SQL> rollback;
Rollback complete.

SQL> explain plan for
  2   select /*+ and_equal(t test_ixa test_ixb) */ rowid
  3     from test t
  4    where a=:1 and b=:2;
Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------
| Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |          |    30 | 90120 |    47   (0)| 00:00:01 | -- 47 =~ 179*(50/100)*(50/100)==44.75
|*  1 |  AND-EQUAL        |          |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| TEST_IXA |   300 |       |    40   (0)| 00:00:01 | -- 40 =~ 79*(50/100)
|*  3 |   INDEX RANGE SCAN| TEST_IXB |   300 |       |    40   (0)| 00:00:01 |
------------------------------------------------------------------------------

SQL> alter session set optimizer_index_cost_adj=25;
Session altered.
SQL> rollback;
Rollback complete.

SQL> explain plan for
  2   select /*+ and_equal(t test_ixa test_ixb) */ rowid
  3     from test t
  4    where a=:1 and b=:2;
Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------
| Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |          |    30 | 90120 |    14   (0)| 00:00:01 | -- 14 =~ 179*(50/100)^4==11.1875
|*  1 |  AND-EQUAL        |          |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| TEST_IXA |   300 |       |    20   (0)| 00:00:01 |
|*  3 |   INDEX RANGE SCAN| TEST_IXB |   300 |       |    20   (0)| 00:00:01 |
------------------------------------------------------------------------------