Проверка NULL параметра в пункте WHERE

У меня проблемы с хранимой процедурой, которая для выполнения занимает около целой вечности. Она довольно большая, и я могу понять, что это займет некоторое время, но эта процедура продолжается почти 20 минут.

После некоторых отладок и исследований я заметил, что замена этой части пункта ГДЕ ;

((p_DrumNo IS NULL) OR T_ORDER.ORDER_ID IN (SELECT ORDER_ID FROM ORDERDELIVERY))

сделала огромную разницу. Так что процедура работает просто отлично до тех пор, пока p_DrumNo - NULL или я модифицирую вышесказанное, чтобы не проверять, не является ли p_DrumNo NULL;

(T_ORDER.ORDER_ID IN (SELECT ORDER_ID FROM ORDERDELIVERY))

Цель этого пункта WHERE - отфильтровать результат, установленный на p_DrumNo, если он передан в Процедуру Хранения. Затем выражение WHERE продолжается с дальнейшими условиями, но именно это условие останавливает запрос.

ORDERDELIVERY - это просто ~временная таблица, содержащая ORDER_IDs, связанные с параметром p_DrumNo.

Как эта простая NULL-проверка может вызвать такое большое влияние? Наверное, это связано с использованием OR вместе с подзапросом, но я не понимаю, почему, так как сам подзапрос работает просто отлично.

Заранее спасибо!

UPDATE [2011-09-23 10:13]

Я разбил проблему на этот небольшой запрос, который показывает то же самое поведение;

Пример A

SQL запроса

SELECT * FROM T_ORDER WHERE
('290427' IS NULL OR ORDER_ID IN (SELECT ORDER_ID FROM T_ORDER WHERE ORDERNO LIKE '290427%') );

План выполнения

OPERATION   OBJECT_NAME     OPTIONS     COST
------------------------------------------------------------
SELECT STATEMENT                    97
FILTER
TABLE ACCESS    T_ORDER         FULL        95
TABLE ACCESS    T_ORDER         BY INDEX ROWID  2
INDEX       PK_ORDER        UNIQUE SCAN 1

Пример B

SQL запроса

SELECT * FROM T_ORDER WHERE
( ORDER_ID IN (SELECT ORDER_ID FROM T_ORDER WHERE ORDERNO LIKE '290427%') );

План выполнения

OPERATION   OBJECT_NAME     OPTIONS     COST
------------------------------------------------------------
SELECT STATEMENT                    4
NESTED LOOPS                        4
TABLE ACCESS    T_ORDER         BY INDEX ROWID  3
INDEX       IX_T_ORDER_ORDERNO  RANGE SCAN   2  
TABLE ACCESS    T_ORDER         BY INDEX ROWID  1  
INDEX       PK_ORDER        UNIQUE SCAN 0

Как вы все видите, первый запрос (пример A) выполняет полное сканирование таблицы. Есть идеи, как этого избежать?

5
задан Stefan 23 September 2011 в 08:13
поделиться