Puzzle d'optimiseur de requête SQL Server 2008 R2
Nous avons deux tableaux, contenant chacun 9 millions de lignes. 70 000 lignes sont différentes, les autres sont les mêmes.
C'est rapide, 13 secondes,
select * from bigtable1
except select * from similar_bigtable2
Cela trie la sortie et est également rapide, 13 secondes également,
select * into #q from bigtable1
except select * from similar_bigtable2
select * from #q order by sort_column
Bien que cela soit extrêmement lent:
;with q as (
select * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
Et même une "astuce" que j'utilise parfois pour indiquer à SQL Server qu'il doit précalculer une certaine partie de la requête avant de continuer, ne fonctionne pas et entraîne également une requête lente:
;with q as (
select top 100 percent * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
En regardant les plans de requête, la raison n'est pas difficile à trouver:

SQL Server place deux sortes de 9 millions de lignes avant le hashmatch, alors que je préférerais qu'il n'ait ajouté qu'une seule sorte de 70 000 lignes après le hashmatch.
Donc, la question: comment puis-je demander à l'optimiseur de requêtes de le faire?
EXCEPT(par exemple OUTER JOIN)? Je me rends compte que la syntaxe est moins pratique, mais vous pourrez peut-être mieux jouer avec les indices d'indexation / jointure (ou vous n'en aurez peut-être pas besoin). L'alternative que vous utilisez maintenant (tout d'abord dans une table #temp) est une solution de dernier recours, mais dans certains cas, c'est la seule façon de forcer l'optimiseur à séparer complètement deux parties d'une requête de la manière que vous souhaitez.