У меня проблемы с планом выполнения моего запроса для запроса среднего размера по большому объему данных в Oracle 11.2.0.2 .0. Чтобы ускорить процесс, я ввел фильтр диапазона, который делает примерно следующее:
PROCEDURE DO_STUFF(
org_from VARCHAR2 := NULL,
org_to VARCHAR2 := NULL)
-- [...]
JOIN organisations org
ON (cust.org_id = org.id
AND ((org_from IS NULL) OR (org_from <= org.no))
AND ((org_to IS NULL) OR (org_to >= org.no)))
-- [...]
Как видите, я хочу ограничить JOIN
из организаций
, используя необязательный диапазон номеров организаций. Клиентский код может вызывать DO_STUFF
с (предположительно быстрым) или без (очень медленным) ограничением.
Проблема в том, что PL / SQL создаст переменные связывания для вышеуказанного org_from
и org_to
параметры, чего я ожидал в большинстве случаев:
-- [...]
JOIN organisations org
ON (cust.org_id = org.id
AND ((:B1 IS NULL) OR (:B1 <= org.no))
AND ((:B2 IS NULL) OR (:B2 >= org.no)))
-- [...]
Только в этом случае я измерил, что план выполнения запроса был намного лучше когда я просто вставляю значения, то есть когда запрос, выполняемый Oracle, на самом деле выглядит примерно как
-- [...]
JOIN organisations org
ON (cust.org_id = org.id
AND ((10 IS NULL) OR (10 <= org.no))
AND ((20 IS NULL) OR (20 >= org.no)))
-- [...]
Под "много" я имею в виду в 5-10 раз быстрее. Обратите внимание, что запрос выполняется очень редко, т.е. раз в месяц. Так что мне не нужно кэшировать план выполнения.
Как я могу встроить значения в PL / SQL? Я знаю о EXECUTE IMMEDIATE , но я бы предпочел, чтобы PL / SQL компилировал мой запрос, и не выполнять конкатенацию строк.
Я просто измерил то, что произошло случайно, или могу предположить, что встраивание переменных действительно лучше (в данном случае)? Причина, по которой я спрашиваю, состоит в том, что я думаю, что переменные связывания вынуждают Oracle разработать общий план выполнения, тогда как встроенные значения позволят анализировать очень специфическую статистику столбцов и индексов . Так что я могу представить, что это не просто совпадение.
Я что-то упускаю? Может быть, есть совершенно другой способ улучшить план выполнения запроса, кроме встраивания переменных (обратите внимание, что я тоже пробовал немало подсказок, но я не эксперт в этой области)?