terça-feira, 16 de junho de 2009

Por que este plano de execução?

Bom dia leitor.
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

Um comentário:

  1. 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.

    Poré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...

    ResponderExcluir