Этот короткая статья, в частности, посвящена применению представления v$object_usage для контроля использования индекса.
Том!
Контролировать использование индекса в Oracle 9i можно, выполнив сначала оператор alter index xxx monitoring usage, начинающего процесс сбора соответствующей информации, а затем выполняя запросы к представлению v$object_usage. Какие операторы DDL или DML при этом будут генерировать 'YES' в столбце 'USED' этого представления? Друкгими словами, будут ли операторы 'select' считаться использующими индекс, или только update?..
Ответ Тома Кайта
Столбец будет иметь значение YES, если индекс использовался для ДОСТУПА к таблице, -- будь-то при изменении, слиянии (merge), удалении строк или при выполнении оператора SELECT. Этот столбец изменяется не потому, что "изменена" какая-то запись индекса -- это будет происходить при каждой вставке. Столбец устанавливается в YES, когда индекс используется для доступа к таблице.
Рассмотрим пример
ops$tkyte@ORA920.US.ORACLE.COM> create table t ( x int,
2 constraint t_pk primary key(x) );
Table created.
ops$tkyte@ORA920.US.ORACLE.COM> insert into t
2 select rownum
3 from all_objects
4 where rownum <= 100
5 /
100 rows created.
ops$tkyte@ORA920.US.ORACLE.COM> set echo off
Теперь включим мониторинг индекса:
ops$tkyte@ORA920.US.ORACLE.COM> select index_name, monitoring, used, start_monitoring, end_monitoring
2 from v$object_usage;
no rows selected
ops$tkyte@ORA920.US.ORACLE.COM> alter index t_pk monitoring usage
2 /
Index altered.
ops$tkyte@ORA920.US.ORACLE.COM> select index_name, monitoring, used, start_monitoring, end_monitoring
2 from v$object_usage;
INDEX_NAME MONITORING USED START_MONITORING END_MONITORING
------------ ---------- ---- ------------------- -------------------
T_PK YES NO 10/05/2003 18:29:16
ops$tkyte@ORA920.US.ORACLE.COM>
ops$tkyte@ORA920.US.ORACLE.COM> set echo off
При использовании оптимизатора, основанного на правилах (RBO), как оно и будет по умолчанию, выборка count(*) идет не через индекс:
ops$tkyte@ORA920.US.ORACLE.COM> set autotrace on explain
ops$tkyte@ORA920.US.ORACLE.COM> select count(*) from t;
COUNT(*)
----------
100
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'T'
ops$tkyte@ORA920.US.ORACLE.COM> set autotrace off
ops$tkyte@ORA920.US.ORACLE.COM> select index_name, monitoring, used, start_monitoring, end_monitoring
2 from v$object_usage;
INDEX_NAME MONITORING USED START_MONITORING END_MONITORING
------------ ---------- ---- ------------------- -------------------
T_PK YES NO 10/05/2003 18:29:16
ops$tkyte@ORA920.US.ORACLE.COM> set echo off
Как и выполнение оператора insert:
ops$tkyte@ORA920.US.ORACLE.COM> insert into t values (-1);
1 row created.
ops$tkyte@ORA920.US.ORACLE.COM> select index_name, monitoring, used, start_monitoring, end_monitoring
2 from v$object_usage;
INDEX_NAME MONITORING USED START_MONITORING END_MONITORING
------------ ---------- ---- ------------------- -------------------
T_PK YES NO 10/05/2003 18:29:16
ops$tkyte@ORA920.US.ORACLE.COM> set echo off
Но если проанализировать таблицу, при выборке count(*) индекс будет использоваться, и мы получим соответствующую запись:
ops$tkyte@ORA920.US.ORACLE.COM> analyze table t compute statistics
2 /
Table analyzed.
ops$tkyte@ORA920.US.ORACLE.COM> set autotrace on explain
ops$tkyte@ORA920.US.ORACLE.COM> select count(*) from t;
COUNT(*)
----------
101
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1)
1 0 SORT (AGGREGATE)
2 1 INDEX (FULL SCAN) OF 'T_PK' (UNIQUE) (Cost=2 Card=101)
ops$tkyte@ORA920.US.ORACLE.COM> set autotrace off
ops$tkyte@ORA920.US.ORACLE.COM> select index_name, monitoring, used, start_monitoring, end_monitoring
2 from v$object_usage;
INDEX_NAME MONITORING USED START_MONITORING END_MONITORING
------------ ---------- ---- ------------------- -------------------
T_PK YES YES 10/05/2003 18:29:16
ops$tkyte@ORA920.US.ORACLE.COM>
Ссылки по теме