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