Question

Supposons que j'ai une instruction SQL comme ce qui suit avec la variable @FOO quelque part plus tôt dans définir le code:

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(FIELD = @FOO OR @FOO IS NULL)

L'optimiseur de requêtes assez intelligent pour faire le deuxième côté du OU premier (@FOO IS NULL) car (une autre hypothèse), il est plus rapide de faire une vérification nul que de faire une comparaison sur le terrain?

Je l'ai fait une analyse comparative informelle et non seulement je ne vois pas une différence, je reçois des temps de résultat sur mes tentatives qui jette la capacité de faire une comparaison.

Était-ce utile?

La solution

La réponse ...

Oui , l'optimisateur est assez intelligent.

La réponse plus ...

SQL est déclarative plutôt que impératif: Votre requête est une description des critères que vos résultats doivent répondre, il est pas instructions étape par étape sur la façon de générer ces résultats

Le Optimiseur exécute la requête dans l'ordre le plus efficace. Il ne garantit pas d'évaluer vos clauses dans un ordre particulier, ou même les évaluer du tout - si l'on peut obtenir des résultats corrects sans évaluer une clause particulière alors pourquoi serait-il la peine

L'ordre d'évaluation réelle d'une requête particulière est un détail de mise en œuvre et peut changer au fil du temps (par exemple, les statistiques sur le changement de table).

Dans la pratique, l'Optimiseur de temps en temps se tromper, mais dans ce cas particulier - comparer une variable à NULL par rapport à la lecture d'une table ou d'un index - Je ne pense pas qu'il y ait beaucoup de chance de ce vissage, bien que vous voudrez peut-être envisager d'utiliser OPTION(RECOMPILE) ou OPTION(OPTIMIZE FOR ...) .

Autres conseils

Essayez de tester avec les clauses dans l'ordre inverse:

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(@FOO IS NULL OR FIELD = @FOO)

Vous trouverez peut-être que le premier test de court-circuit le second, mais pas vice-versa.

Dans mon expérience, il est parfois encore plus rapide d'utiliser deux requêtes et une « UNION » au lieu d'une clause « OU ».

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(FIELD = @FOO)

UNION

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(@FOO IS NULL)

Cette approche présente l'inconvénient de dupliquer l'instruction SELECT, mais l'augmentation de la performance de 1500% a été la justifier. Bien sûr, cela dépend de la structure de base de données (dans mon cas, il était tout à fait mal, et je ne pouvais pas changer).

Il est assez intelligent pour appliquer la condition première plus rapide, en supposant qu'il peut juger que la comparaison sera plus rapide dans le cas général. Dans ce cas, le chèque NULL sera presque toujours plus rapide car il doit comparer au maximum un octet de chaque côté de l'expression et peut tenir dehors.

Un facteur qui peut être en jeu ici si cette requête est à l'intérieur d'un sproc est « paramètre renifler ». Cela peut conduire à des temps de réponse des requêtes incompatibles. Pour corriger cela déclarer une variable interne dans votre sproc et affecter cette variable à la valeur du paramètre puis utilisez la variable interne dans votre clause where ou utilisez la balise recompiler clause dans votre sproc. Il y a beaucoup de liens sur ce sujet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top