Принудительное использование индекса в Oracle - PullRequest
32 голосов
/ 03 декабря 2009

Я столкнулся с этим вопросом в интервью и понятия не имел, как ответить:

Есть таблица с индексом по столбцу, и вы запрашиваете:

select * from table_name where column_having_index="some value";

Запрос занимает слишком много времени, и вы обнаруживаете, что индекс не используется. Если вы считаете, что при использовании индекса производительность запроса будет лучше, как заставить запрос использовать индекс?

Ответы [ 5 ]

43 голосов
/ 03 декабря 2009

Вы можете использовать подсказки оптимизатора

select /*+ INDEX(table_name index_name) */ from table и т.д ...

Подробнее об использовании подсказок оптимизатора: http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/hintsref.htm

13 голосов
/ 03 декабря 2009

Может быть много причин , если индекс не используется. Даже после того, как вы укажете подсказки , есть вероятность, что оптимизатор Oracle сочтет иначе, а решит не использовать индекс . Вам нужно пройти через часть EXPLAIN PLAN и посмотреть, сколько стоит выписка с INDEX и без INDEX.

Предполагая, что Oracle использует CBO . Чаще всего, если оптимизатор считает, что стоимость с INDEX высока, даже если вы укажете ее в подсказках, оптимизатор будет игнорировать и продолжать полное сканирование таблицы. Ваше первое действие должно проверять DBA_INDEXES, чтобы знать, когда статистика LAST_ANALYZED. Если не проанализировано, вы можете установить таблицу, индекс для анализа .

begin 
   DBMS_STATS.GATHER_INDEX_STATS ( OWNNAME=>user
                                 , INDNAME=>IndexName);
end;

Для таблицы.

begin 
   DBMS_STATS.GATHER_TABLE_STATS ( OWNNAME=>user
                                 , TABNAME=>TableName);
end;

В крайних случаях вы можете попробовать настроить статистику самостоятельно.

12 голосов
/ 03 декабря 2009

Если вы считаете, что при использовании индекса производительность запроса будет выше, как вы можете заставить запрос использовать индекс?

Сначала вы, конечно, убедитесь, что индекс дал лучший результат для возврата полного набора данных, верно?

Подсказка индекса является ключевым моментом здесь, но более современный способ ее указания - это метод именования столбцов, а не метод именования индексов. В вашем случае вы бы использовали:

select /*+ index(table_name (column_having_index)) */ *
from   table_name
where  column_having_index="some value"; 

В более сложных случаях вы могли бы ...

select /*+ index(t (t.column_having_index)) */ *
from   my_owner.table_name t,
       ...
where  t.column_having_index="some value"; 

Что касается составных индексов, я не уверен, что вам нужно , чтобы указать все столбцы, но это хорошая идея. См. Документы здесь http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#autoId18 для нескольких index_specs и использование index_combine для нескольких индексов, а здесь http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#BABGFHCH для спецификации нескольких столбцов в index_spec.

2 голосов
/ 03 декабря 2009

Существует соответствующий индекс для column_having_index, и его использование на самом деле повышает производительность, но Oracle его не использует ...
Вы должны собрать статистику в своей таблице, чтобы оптимизатор увидел, что доступ к индексу может помочь. Использование прямой подсказки не является хорошей практикой.

0 голосов
/ 03 декабря 2009

Вы можете использовать:

WITH index = ...

подробнее

...