Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

Чтобы "заставить" 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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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