У меня проблемы с хранимой процедурой, выполнение которой занимает вечность. Он довольно большой, и я могу понять, что мне потребуется некоторое время, но это продолжается почти 20 минут.
После некоторой отладки и исследования я заметил, что замена этой части предложения WHERE
;
((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_ID, связанные с параметром p_DrumNo.
Как эта простая проверка IS NULL может оказать такое большое влияние? Вероятно, это связано с использованием OR
вместе с подзапросом, но я не понимаю, почему сам подзапрос работает просто отлично.
Заранее спасибо!
ОБНОВЛЕНИЕ [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) выполняет полное сканирование таблицы. Любые идеи о том, как я могу избежать этого?