Теперь у меня есть действительно сложная вещь с планами выполнения Oracle, приводящими в хаос, когда я использую функцию DETERMINISTIC
справа от оператора LIKE
. Это моя ситуация:
Ситуация
Я подумал, что было бы разумно выполнить такой запрос (упрощенный):
SELECT [...]
FROM customers cust
JOIN addresses addr ON addr.cust_id = cust.id
WHERE special_char_filter(cust.surname) like special_char_filter(?)
И я бы привязал ?
к чему-то вроде 'Eder%'
. Теперь customers
и addresses
очень большие таблицы. Вот почему важно использовать индексы. Конечно, на addresses.cust_id
есть обычный индекс. Но я также создал функциональный индекс для special_char_filter(customers.surname)
, который работает очень хорошо.
Проблема
Проблема в том, что приведенный выше запрос с предложением like
создает планы выполнения с ПОЛНЫМ СКАНИРОВАНИЕМ ТАБЛИЦЫ на addresses
. Похоже, что-то в этом запросе не позволяет Oracle использовать индексы для addresses.cust_id
.
Обходной путь
Я узнал, что решение моей проблемы таково:
SELECT [...]
FROM customers cust
JOIN addresses addr ON addr.cust_id = cust.id
WHERE special_char_filter(cust.surname) like ?
Я удалил функцию (DETERMINISTIC
!) из правой части аналогичного оператора и предварительно вычислил переменную связывания в Java. Теперь этот запрос сверхбыстрый, без ПОЛНОГО СКАНИРОВАНИЯ ТАБЛИЦ. Это тоже очень быстро (хотя и не эквивалентно):
SELECT [...]
FROM customers cust
JOIN addresses addr ON addr.cust_id = cust.id
WHERE special_char_filter(cust.surname) = special_char_filter(?)
Путаница
Я этого не понимаю. Что плохого в наличии детерминированных функций в правой части оператора like
? Я наблюдал это в Oracle 11.2.0.1.0.