2010-03-18 3 views
12

У меня есть серия очень похожих запросов, которые я выполняю против таблицы в 1,4 миллиарда записей (с индексами), единственная проблема заключается в том, что по меньшей мере 10% этих запросов занимают> 100 раз больше времени для выполнения, чем другие.Как заставить оракул использовать сканирование диапазона индекса?

Я запустил план объяснений и заметил, что для быстрых запросов (примерно 90%) Oracle использует сканирование диапазона индексов; на медленных, он использует полное сканирование индекса.

Есть ли способ заставить Oracle делать сканирование диапазона индекса?

ответ

12

я предлагаю следующий подход: -

  • Получить объяснить план на медленном заявлении
  • с помощью индекса подсказку, получить план объяснить на использование индекса

Вы обратите внимание, что стоимость плана INDEX больше. Вот почему Oracle не выбирает индексный план. Стоимость - это оценка Oracle, основанная на статистике и различных допущениях.

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

Чтобы понять, почему это неправильно, посмотрите на количество ожидаемых строк в плане. Вы, вероятно, найдете один из них на порядок. Это может быть связано с неравномерно распределенными значениями столбцов, старой статистикой, столбцами, которые взаимосвязаны друг с другом и т. Д.

Чтобы решить эту проблему, вы можете получить Oracle для сбора лучшей статистики и намека на нее с лучшими исходными предположениями. Затем он оценит точные затраты и придумает самый быстрый план.

Если вы разместите больше информации, я могу комментировать дальше.

+3

Учитывая, что это сканирование диапазона, я задаюсь вопросом, имеют ли «медленные» запросы более широкий диапазон (например, год вместо недели). В этом случае вы ожидаете, что они будут значительно медленнее. В какой-то момент, когда диапазон будет достаточно большим, будет иметь смысл перейти от индекса к полному сканированию. Означает ли Oracle, что точка правильно, это другое дело. –

+0

Кроме того, если он выполняет полное сканирование индекса и ваш запрос присоединяется к другой таблице, я бы предположил, что он не соединяется через вложенный цикл - это, вероятно, переход на хеш-соединение или объединение слияния или объединение таблиц в другом порядке. Если медленные запросы «должны» быть более быстрыми (т. Е. Они не IRL, запрашивающие значительную часть таблицы), вы должны иметь возможность вернуться к сканированию диапазона, указав на вложенные циклы (с подходящим подсказкой 'USE_NL'). –

-2

Я видел, что намек игнорируется Oracle.

В последнее время наш DBA использует «optimizer_index_cost_adj», и он использовал индекс. Это параметр Oracle, но вы можете использовать его как уровень сеанса.

100 - значение по умолчанию, и мы использовали параметр 10 в качестве параметра.

+0

optimizer_index_cost_adj влияет на ВСЕ вычисления, сделанные оптимизатором при рассмотрении ЛЮБЫХ индексов по всей системе. Изменение должно быть выполнено тщательно, учитывая его общий аффект в системе. –

+0

Это моя точка. Когда он используется, он должен использоваться параметром уровня сеанса, чтобы он не влиял на какой-либо другой запрос. – exiter2000

+0

Пожалуйста, помните, что подсказки - это подсказки и что оптимизатор может решить не использовать его. – DJPeter

2

Если вы хотите знать, почему оптимизатор принимает решения, вам нужно использовать трассировку 10053.

SQL> alter session set events '10053 trace name context forever, level 1'; 

Затем запустите пояснения для примера быстрого запроса и выборочного медленного запроса. В каталоге дампа пользователя вы получите файлы трассировки с подробным описанием деревьев решений, которые проходят CBO. Где-то в этих файлах вы найдете причины, по которым он выбирает полное сканирование индекса по сканированию диапазона индексов.

Я не говорю, что файлы трассировки легко читаются. Лучшим ресурсом для их понимания является превосходная статья Вольфганга Брейтлинга "A look under the hood of CBO" (PDF)

-1

вы можете использовать подсказки оракула sql.Вы можете заставить использовать конкретный индекс или исключения индекса проверить документацию

http://psoug.org/reference/hints.html http://www.adp-gmbh.ch/ora/sql/hints/index.html

как выберите/* + index (scott.emp ix_emp) */from scott.emp emp_alias

+1

Это сделает Oracle использование индекса, но не обязательно приведет к сканированию диапазона индексов вместо полного сканирования индекса. –

+0

Если ваш индекс основан на значениях, отличных от уникальных столбцов, это, безусловно, будет идти только для сканирования диапазона индексов. Чтобы сделать это с помощью подсказки, используйте подсказку подсказки, и все должно быть хорошо. в противном случае для полного сканирования индекса требуется – mermerkaya

+0

Вероятно, 99,9% времени он правильно выбирает сканирование диапазона индекса. Но иногда Oracle выбирает полное сканирование индекса. Есть подсказка, чтобы сказать Oracle не использовать * быстрое * полное сканирование индексов, но насколько я знаю, нет никакого способа сказать Oracle не использовать полное сканирование индекса. –

7

Чтобы заставить «Oracle» использовать сканирование диапазона индексов, просто используйте подсказку оптимизатора INDEX_RS_ASC. Например:

CREATE TABLE mytable (a NUMBER NOT NULL, b NUMBER NOT NULL, c CHAR(10)) NOLOGGING; 

INSERT /*+ APPEND */ INTO mytable(a,b,c) 
SELECT level, mod(level,100)+1, 'a' FROM dual CONNECT BY level <= 1E6; 

CREATE INDEX myindex_ba ON mytable(b, a); 
EXECUTE dbms_stats.gather_table_stats(NULL,'mytable'); 

SELECT /*+ FULL(m)   */ b FROM mytable m WHERE b=10; -- full table scan 
SELECT /*+ INDEX_RS_ASC(m) */ b FROM mytable m WHERE b=10; -- index range scan 
SELECT /*+ INDEX_FFS(m) */ b FROM mytable m WHERE b=10; -- index fast full scan 

ли это будет сделать запрос на самом деле работает быстрее, зависит от многих факторов, таких как селективность индексированной стоимости или физического порядка строк в таблице. Например, если вы измените запрос WHERE b BETWEEN 10 AND <xxx>, следующие расходы появляются в планах выполнения на моей машине:

b BETWEEN 10 AND 10  20  40  80 
FULL    749 750  751 752 
INDEX_RS_ASC  29 325  865 1943 
INDEX_FFS   597 598  599 601 

Если вы слегка изменить запрос, чтобы не только выбрать индексированный столбец b, но и другие, неиндексные столбцы, затраты резко меняются:

b BETWEEN 10 AND 10  20  40  80 
FULL    749 750  751 754 
INDEX_RS_ASC  3352 40540 108215 243563 
INDEX_FFS   3352 40540 108215 243563 
+0

Я изменил INDEX_RS на INDEX_RS_ASC. Оба работают, но на основе V $ SQL_HINT и [этой статьи] (http://jonathanlewis.wordpress.com/2007/06/17/hints-again/) INDEX_RS_ASC представляется официальным намеком, хотя оба они действительно без документов. К сожалению, этот намек по-прежнему не решает мою конкретную проблему, поэтому она не всегда работает. Но это работает, по крайней мере, иногда, как ясно показывает ваш сценарий. –

Смежные вопросы