Vérifier si le paramètre est NULL dans la clause where

Im de la difficulté avec une Procédure Stockée qui prend environ une éternité à exécuter. Il est assez grand et je peux comprendre que les Mauvais de prendre un certain temps, mais celui-ci se poursuit pendant près de 20 minutes.

Après un peu de débogage et de la recherche, j'ai remarqué que le remplacement de cette partie de la WHERE clause;

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

fait une ÉNORME différence. Si la Procédure fonctionne très bien aussi longtemps que p_DrumNo est NUL ou que je modifie le ci-dessus de ne pas cocher si p_DrumNo est NULLE;

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

L'objectif avec ce WHERE clause est de filtrer le résultat sur p_DrumNo si son passé à la Procédure Stockée. Le WHERE clause continue ensuite avec d'autres conditions, mais ce un point d'arrêt à la requête.

ORDERDELIVERY est juste un ~table temporaire contenant ORDER_IDs concerne le paramètre p_DrumNo.

Comment cela peut-il simple EST NULL-vérifier provoquer un tel grand impact? C'est probablement lié à l'utilisation de OR en collaboration avec la sous-requête mais je ne comprends pas pourquoi que la sous-requête elle-même fonctionne très bien.

Merci d'avance!

Mise à JOUR [2011-09-23 10:13]

Ive décompose le problème dans cette petite requête qui montrent le même comportement;

Exemple Un

Requête SQL

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

Plan d'exécution

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

Exemple B

Requête SQL

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

Plan d'exécution

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

Comme vous pouvez le voir, la première requête (exemple A) une analyse de la table. Des idées sur comment je peux l'éviter?

Vous pouvez poster l'instruction SQL complète et le plan de requête dans les deux cas? Est OrderDelivery une table temporaire globale? Ou une table permanente où les données sont transitoires? Comment sélective est ce prédicat?
OrderDelivery est une table temporaire dans un curseur. Je préfère ne pas inclure l'ensemble de la procédure mais j'ai mis à jour ma question avec un exemple. Merci

OriginalL'auteur Stefan | 2011-09-22