Optimisation de requêtes SQL - utilisation de IN SELECT
Bonjour,
Je souhaiterais avoir des avis éclairés sur l'optimisation de requêtes car depuis peu j'essai de de comprendre le plan d'exécution fourni dans l'analyseur de requête de SQL Server.
Voici un cas d'école proposant deux requêtes différentes pour le même résultat :
1)
select * from T1
where T1.codeT2 not in (select codeT2 from T2)
2)
select * from T1
left join T2
on T2.codeT2 = T1.codeT2
where T2.codeT2 is null
Je serais tenté de croire que la seconde est plus efficace, mais en analysant le plan d'exécution je commence à douter.
Plan d'exécution :
1)
Coût d'exécution de la requête en fonction du lot (50%)
SELECT (coût 100%) <-- Nested Loops/Left Anti Semi Join (Coût 0%)
<-- Clustered Index Scan (Coût 75%)
<-- Index Seek (Coût 200%)
2)
Coût d'exécution de la requête en fonction du lot (50%)
SELECT (coût 0%) <-- Filter (Coût 0%) <-- Bookmark Lookup (Coût 100%)
<-- Nested Loops /Left Outer Join (Coût 0%)
<-- Clustered Index Scan (Coût 75%)
<-- Index Seek (Coût 200%)
Dans certain cas (on fonction des données), la première requête semble même plus rapide (le coût d'exécution de la requête en fonction du lot passe à 33% / 67% en faveur de la première --> avec le In Select).
Suite à ce constat j'ai donc deux questions "existencielles" à poser :
- tout ce qu'on m'a dit jusqu'à aujourd'hui comme quoi le "IN SELECT" serait à proscrire autant que possible est faux ?
- comment dois-je comprendre le plan d'exécution (à quoi correspondent les pourcentages, la taille des flèches, etc...) ? - connaissez-vous un ou plusieurs sites expliquant comment l'analyser ?
IN - Exists - Any - Left Join --> plan d'exécution
Je ne connais pas trop la différence entre le IN et les deux autres mots clés Exists et Any.
Les trois requêtes suivantes affichent exactement le même plan d'exécution :
select * from factur
where factur.sy_fac not in (select sy_fac from boncde)
select * from factur
where not factur.sy_fac = any (select sy_fac from boncde)
select * from factur
where not exists
(select boncde.sy_fac from boncde
where boncde.sy_fac = factur.sy_fac)