Принудительное использование индекса в Oracle

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

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

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

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


person Vijay    schedule 03.12.2009    source источник


Ответы (6)


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

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

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

person Rene    schedule 03.12.2009
comment
Кроме того, в более поздних версиях Oracle (я думаю, 10g+) вы можете указать имя столбца вместо имени индекса, например. /*+INDEX(table_name column_having_index)*/ - person Jeffrey Kemp; 03.12.2009
comment
/*+INDEX(table_name (column_having_index))*/ ... opr см. мой ответ для более сложного синтаксиса - person David Aldridge; 03.12.2009
comment
Правильный синтаксис (вы должны использовать псевдоним таблицы!): select /*+ INDEX(xxxTABLExxx index_name) */ from table_name xxxTABLExxx - person xnagyg; 08.04.2016

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

Предположим, что Oracle использует CBO. Чаще всего, если оптимизатор считает, что стоимость ИНДЕКС высока, даже если вы укажете это в подсказках, оптимизатор проигнорирует и продолжит полное сканирование таблицы. Вашим первым действием должна быть проверка 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;

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

person Guru    schedule 03.12.2009
comment
CBO всегда будет учитывать все правильно указанные подсказки — он не может произвольно не принимать подсказки. - person Jeffrey Kemp; 03.12.2009
comment
Совсем недавно мы обновили ORA 9208 с ORA 9205, после этого мы столкнулись с этим, был сложный запрос, INDEX не использовался. Я заставил это с ПОДСКАЗКОЙ. Несмотря на то, что EXPLAIN_PLAN показал, что он использует INDEX, при выполнении он выбрал другой путь. Именно тогда DBA предложил нам переписать SQL. И мы так сделали, это сработало. - person Guru; 03.12.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_spec и использования index_combine для нескольких индексов, а здесь person David Aldridge    schedule 03.12.2009

comment
Как насчет того, если индекс включает несколько столбцов? Нужно ли указывать их все? - person shindigo; 22.03.2013
comment
Улучшен ответ для нескольких столбцов, @shindigo - person David Aldridge; 23.03.2013

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

person Egor Rogov    schedule 03.12.2009
comment
Советы по индексированию, безусловно, следует использовать с осторожностью, но существует множество законных ситуаций для их использования. Одним из примеров является случай, когда статистика недоступна, чтобы продемонстрировать, что значения столбцов сильно коррелированы, а CBO делает неверный вывод о количестве элементов для предикатов в нескольких столбцах. - person David Aldridge; 03.12.2009
comment
Дэвид, что касается вопроса, то пример настолько прост, что я не вижу причин для CBO не использовать индексное сохранение для некорректной статистики. А вообще -- вы правы, конечно. - person Egor Rogov; 03.12.2009

Я пробовал много форматов, но сработало только это:

select /*+INDEX(e,dept_idx)*/ * from emp e;
person xnagyg    schedule 19.02.2021

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

WITH index = ...

подробнее информация

person Leon    schedule 03.12.2009
comment
ооо .. думал, что вы имеете в виду MS-Sql ... но вы поняли :) - person Leon; 03.12.2009