Как заставить оракула использовать сканирование диапазона индекса? - PullRequest
13 голосов
/ 19 марта 2010

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

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

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

Ответы [ 5 ]

12 голосов
/ 19 марта 2010

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

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

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

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

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

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

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

9 голосов
/ 14 декабря 2012

Чтобы «заставить» 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
2 голосов
/ 19 марта 2010

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

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

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

Я не говорю, что файлы трассировки легко читаются. Лучшим источником для их понимания является превосходная техническая статья Вольфганга Брайтлинга «Взгляд под капот CBO» (PDF)

0 голосов
/ 13 декабря 2012

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

http://psoug.org/reference/hints.html http://www.adp -gmbh.ch / ор / SQL / подсказки / index.html

как выберите / * + индекс (scott.emp ix_emp) * / из scott.emp emp_alias

0 голосов
/ 19 марта 2010

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

Недавно наш администратор баз данных использовал "optimizer_index_cost_adj" и использовал индекс. Это параметр Oracle, но вы можете использовать его в качестве уровня сеанса.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...