Forcer un UNION sur une OU pour l'optimisation dans SQL Server 2000
-
21-08-2019 - |
Question
Comment puis-je obtenir une requête qui utilise un OU dans la clause WHERE de se diviser en deux requêtes avec une UNION lors de la compilation? Si je réécris manuellement, la requête en utilisant l'UNION est 100x plus rapide que la seule requête, car il peut utiliser efficacement différents indices dans chaque requête du syndicat. Est-il possible que je puisse faire l'optimiseur utiliser cette approche?
J'ai une requête qui ressemble à quelque chose comme ceci:
select columnlist
from table1
join table2 on joincond2
join table3 on joincond3
where conditions1
and ((@param1 is null and cond3a) or (cond3b))
Où COLUMNLIST, joincond2, joincond3 et conditions1 sont toutes les expressions plus longues. Le botteur est que seule une des conditions du OU est toujours vrai.
J'ai d'abord pensé que je pouvais réécrire pour faire l'union, mais je répète COLUMNLIST, joincond2, joincond3 et conditions1, qui est 20 ou si des lignes de SQL qui pourraient avoir besoin de beaucoup d'entretien à l'avenir. Y at-il un indice que je peux fournir ou une meilleure façon d'écrire la clause WHERE? Merci à l'avance.
La solution
Vous pouvez regrouper
select columnlist
from table1
join table2 on joincond2
join table3 on joincond3
dans une vue, puis utilisez l'union.
mais si vous pouvez migrer vers sql2005 / 8, vous pouvez utiliser l'expression de table commune.
with cte ( columnlist )
as (
select columnlist
from table1
join table2 on joincond2
join table3 on joincond3 )
select columnlist from cte where ...
union
select columnlist from cte where ...
Autres conseils
Essayez d'ajouter OPTION (RECOMPILE) à la requête. Si elle est dans une procédure stockée puis ajouter WITH RECOMPILE à cela aussi. Il se peut que la première fois que vous exécutez la requête SQL Server est livré avec un plan et il met en cache mais la deuxième fois par qu'il utilise encore l'ancien (et maintenant pauvres) plan de requête.
Vous prenez un coup mineur, car il devra recompiler chaque fois que vous utilisez la requête, mais il sera infime par rapport à l'utilisation d'un mauvais plan.
EDIT: J'ai lu que l'utilisation WITH RECOMPILE dans une procédure stockée dans SQL 2000 ne fonctionne pas toujours correctement. Le bogue a été soi-disant résolu dans SQL 2005. Je ne l'ai jamais rencontré personnellement le bug, donc je ne sais pas ce que l'affaire est exacte avec elle. Faites un essai bien.