Puzle Otimizador de consultas do SQL Server 2008 R2
Temos duas tabelas, ambas contendo 9 milhões de linhas. 70.000 linhas são diferentes, as outras são iguais.
Isso é rápido, 13 segundos,
select * from bigtable1
except select * from similar_bigtable2
Isso classifica a saída e também é rápido, 13 segundos também,
select * into #q from bigtable1
except select * from similar_bigtable2
select * from #q order by sort_column
Embora isso seja muito lento:
;with q as (
select * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
E mesmo um "truque" que às vezes uso para sugerir ao SQL Server que ele precisa pré-calcular uma certa parte da consulta antes de prosseguir, não funciona e resulta em consulta lenta também:
;with q as (
select top 100 percent * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
Observando os planos de consulta, não é difícil encontrar o motivo:

O SQL Server coloca dois tipos de 9 milhões de linhas antes do hashmatch, enquanto eu preferiria ter adicionado apenas um tipo de 70.000 linhas após o hashmatch.
Então a pergunta: como instruir o otimizador de consulta para fazer isso?
EXCEPT(por exemplo OUTER JOIN)? Sei que a sintaxe é menos conveniente, mas você pode jogar com dicas de índice / junção melhor lá (ou talvez não seja necessário). A alternativa que você está usando agora (primeiro em uma tabela #temp) é uma solução alternativa de último recurso, mas em alguns casos é a única maneira de forçar o otimizador a separar completamente duas partes de uma consulta da maneira que desejar.