J'ai un problème où j'ai besoin de find des loggings qui ont une mesure qui correspond à une valeur, ou qui n'ont pas cette mesure du tout. J'ai résolu ce problème avec 3 ou 4 approches différentes, en utilisant des joins
, en utilisant not in
et en utilisant not exists
. Cependant, la requête a fini par être extrêmement lente à chaque fois. J'ai ensuite essayé de scinder la requête en deux, et tous les deux fonctionnent très vite (3 secondes). Mais combiner les requêtes en utilisant OR
prend> 5 minutes.
En lisant SO, j'ai essayé UNION
, qui est très rapide, mais très gênant pour le script que j'utilise.
Donc 2 questions: 1: Pourquoi UNION est-il tellement plus rapide? (Ou pourquoi OR
est si lent)? 2: Y a-t-il un moyen de forcer MSSQL à utiliser une approche différente pour l'instruction OR
qui est rapide?
Merci.
La raison en est que l'utilisation de OR
dans une requête entraîne souvent l'utilisation de l'outil d'optimization des requêtes pour abandonner l'utilisation des searchs d'index et revenir aux parsings. Si vous examinez les plans d'exécution de vos deux requêtes, vous verrez très probablement des scans dans lesquels vous utilisez l' OR
et searchz où vous utilisez UNION
. Sans voir votre requête, il n'est pas vraiment possible de vous donner des idées sur la façon dont vous pourriez restructurer la condition OR
. Mais vous pouvez find qu'insert les lignes dans une table temporaire et y adhérer peut donner un résultat positif.
En outre, il est généralement préférable d'utiliser UNION ALL
plutôt que UNION
si vous souhaitez get tous les résultats, car vous supprimez le coût de la correspondance des lignes.
SQL Server ne peut actuellement pas forcer un plan d'exécution UNION
si aucune instruction UNION
n'a été utilisée. Si la seule différence entre les deux parties est la clause WHERE
, créez une vue avec la requête complexe. La requête UNION
devient alors très simple:
SELECT * FROM dbo.MyView WHERE <cond1> UNION ALL SELECT * FROM dbo.MyView WHERE <cond2>
Il est important d'utiliser UNION ALL
dans ce context quand c'est possible. Si vous utilisez juste UNION
SQL Server doit filterr les lignes en double, ce qui nécessite une opération de sorting coûteuse dans la plupart des cas.