У нас есть две таблицы, такие как:
Event
id
type
... a bunch of other columns
ProcessedEvent
event_id
process
Есть индексы, определенные для
- Событие (id) (PK)
- ProcessedEvent (event_id, process)
Первый представляет события в приложении.
Второе представляет тот факт, что определенное событие получило процессы от определенного процесса. Существует много процессов, которые должны обрабатывать определенное событие, поэтому во второй таблице есть несколько записей для каждой записи в первой.
Чтобы найти все события, требующие обработки, мы выполняем следующий запрос:
select * // of course we do name the columns in the production code
from Event
where type in ( 'typeA', 'typeB', 'typeC')
and id not in (
select event_id
from ProcessedEvent
where process = :1
)
Статистика актуальна
Поскольку большинство событий обрабатываются, я думаю, что лучший план выполнения должен выглядеть примерно так
- полное сканирование индекса по индексу ProcessedEvent
- полное сканирование индекса по индексу событий
- анти-соединение между двумя
- доступ к столу с остальными
- фильтр
Вместо этого Oracle делает следующее
- полное сканирование индекса по индексу ProcessedEvent
- полное сканирование таблицы на таблице событий
- фильтр таблицы событий
- анти-соединение между двумя наборами
С указанием индекса я заставляю Oracle делать следующее:
- полное сканирование индекса по индексу ProcessedEvent
- полное сканирование индекса по индексу событий
- таблица доступа к таблице событий
- фильтр таблицы событий
- анти-соединение между двумя наборами
что действительно глупо ИМХО.
Итак, мой вопрос: что может быть причиной того, что оракул настаивает на раннем доступе к таблице?
Дополнение:
Производительность плохая. Мы решаем проблему с производительностью, выбирая только Event.ID и затем выбирая нужные строки «вручную». Но, конечно, это всего лишь обходной путь.