2015-05-21 6 views
1

У меня есть длинный запрос, но похож на укороченный вариант здесь:Oracle выбирает неправильный индекс при соединении таблицы

select * from table_a a 

left join table_b b on 

b.id = a.id and 
b.name = 'CONSTANT'; 

Есть 2 индексов на table_b как для id и name, idx_id имеет меньше дубликатов и idx_name имеет много дубликатов. Это довольно большая таблица (20M + записи). И join принимает 10мин +.

Простая схема объяснения показывает, как много использования памяти в части соединения, и она показывает, что она использует индекс для name, а не id.

Как решить эту проблему? Как заставить использовать индекс idx_id?

Я думал о том, чтобы положить b.name='CONSTANT' в предложение where, но это левое соединение и где будет удаляться вся запись, которая существует в table_a.


Обновленный план объяснения. Извините, вы не можете вставить весь план.

Объяснить план с b.name='CONSTANT':

Wrong index

Объясните план, комментируя b.name пункт:

enter image description here

+2

* Простой объяснить план показывает много памяти использует на джойна части, и это показывает, что он использует индекс для имени, а не id. * Итак, где план объяснения? –

+0

@LalitKumarB добавлено – texasbruce

+0

Ваша статистика в актуальном состоянии на обеих таблицах? – Nick

ответ

0

Добавить оптимизатора намек на ваш запрос.

Не зная ваш «длинный» запрос, трудно понять, использует ли Oracle неправильный или если ваша интерпретация indexb < indexa поэтому поэтому должна быть быстрее для запроса z является правильным.

Чтобы добавить подсказку синтаксис

select /*+ index(table_name index_name) */ * from ....; 
0

Каков размер TABLE_A относительно TABLE_B? Было бы бессмысленно использовать индекс ID, если у TABLE_A было значительно меньше строк, чем TABLE_B.

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

Кроме того, это может помочь, если вы не можете в полной мере объяснить план, используя этот формат текста:

explain plan for select ... ; 
select * from table(dbms_xplan.display); 
Смежные вопросы