Hoje eu vou trazer um ponto de interrogação para vocês, pois de vez em quando eu também esbarro em alguns detalhes que me deixam muito curioso para entender melhor como o SQL Server funciona. Quer ver?
Durante o treinamento de SQL Server 2008 Internals que eu estava ministrando, nós esbarramos em um plano de execução que se mostrou ligeiramente pior que o outro, em um momento onde eu esperava planos iguais. Teste aí...
USE AdventureWorks2008
go
select *
from sales.salesorderheader
where orderdate < '20010710'
go
select *
from sales.salesorderheader with(index(1))
where orderdate < '20010710'
go
Analisando os planos de execução eu obtive o seguinte resultado:
(Figura 01)
Notem que a primeira consulta é um pouco mais cara que a segunda (51% vs. 49%) e a diferença está no local onde o filtro (orderdate < ‘20071001’) é aplicado. Na primeira consulta o filtro é aplicado após a varredura as páginas do índice cluster (figura 02), gerando vTables maiores entres os passos do plano, enquanto na segunda consulta o SQL Server aplica o filtro no momento em que as páginas de dados (nível folha) são percorridas (figura 03).
(Figura 02)
(Figura 03)
A diferença entre os custos de execução já foi entendida, mas deixo aqui algumas perguntas...
1) Se com a hint eu forcei o SQL Server a usar o mesmo índice que ele escolheu para a primeira consulta, o plano de execução deveria ser o mesmo, não?
2) Porque no primeiro caso o SQL Server optou por fazer o filtro somente no fim? Sempre que penso no otimizador de consultas, imagino ele aplicando os filtros o quanto antes, para evitar vTables maiores e operações de maior custo no decorrer da execução.
Só para te poupar o trabalho, é claro que as estatísticas estão atualizadas e o custo de I/O é o mesmo para ambas as consultas, o tempo é obviamente diferente por conta do tamanho da vTables geradas e do filtro. Quando estiver fazendo os seus testes, recomendo usar o DBCC FREEPROCCACHE para não ficar caindo no mesmo plano de execução que está em cache (e foi parametrizado pelo SQL Server - note o “@1” na figura 01).
E aí, conhece o SQL Server? Então conte para todo mundo o que está acontecendo...
Em um próximo post eu detalho um pouco o comportamento do SQL Server para este caso e tento desvendar parte do mistério.
Nota: reproduzi o comportamento no SQL Server 2008 RTM e SP1. Quem testar em outras versões me conte.
Prefere ler o PDF? Baixe aqui.
[]s
Luciano Caixeta Moreira - {Luti}
Chief Innovation Officer
Sr. Nimbus Serviços em Tecnologia Ltda
E-mail: luciano.moreira@srnimbus.com.br
Ummmm, me parece que como existem 2 colunas calculadas na tabela o QO acha que não compensa ler os dados e fazer o filtro direto nas páginas, por isso opta pelo Filter. Se você remover estas colunas verá que ele não gera o Filter.
ResponderExcluirPorém quando você força o uso do Indice, força a leitura direto nas páginas.
Ummm, preciso testar... se eu arrumar um tempo, vou tentar entender :-)... muito bom post...