Fabiano Neves's profileFabiano Neves Amorim - S...PhotosBlogListsMore ![]() | Help |
|
September 11 Query Optimizer - DATE_CORRELATION_OPTIMIZATION
Aqui estou em São Paulo, me preparando para passar as noites do fim de semana acompanhando uma implantação…. Tempo para um post… Pessoal, desde o SQL Server 2005, temos um parâmetro que pode ser habilitado no banco de dados chamado DATE_CORRELATION_OPTIMIZATION. Como o padrão é OFF, eu particularmente nunca vi alguem alterar este parâmetro para ON. Eu creio que isso deve se ao fato de termos pouquíssimo material falando sobre esta feature. É importante que o desenvolvedor ou DBA conheçam o banco de dados, para poder fazer proveito desta otimização, mas você deve estar se pergutando, Mas pra que serve este parâmetro? Vamos lá: Quando habilitado o DATE_CORRELATION_OPTIMIZATION coleta informações sobre colunas do tipo datetime de duas tabelas que estão ligadas por uma foreign key. Estas informações são comumentes conhecidas como estatisticas (apesar de não agirem exatamente como uma estatistica), pois elas ajudam o Query Optimizer a identificar uma relação entre as colunas que contém uma data, e assim decidir sobre a criação do plano de execução. Um bom exemplo de colunas correlatas seria o seguinte: Uma tabela de Pedido que contem uma coluna DataPedido, e uma tabela Itens que contem uma coluna DataEntregaItem. Estes dias eu fiz uma compra no Submarino e comprei varios produtos, desde livros a bichos de pelucia (deixa eu explicar melhor esse item pra não dar chance de aparecerem comentários sobre isso…rs. Foi pra minha patroa gente… é que ela gosta de pinguin e comprei um de pelucia…). Conclusão, apesar de meu pedido ser apenas um, eu recebi os itens em dias diferentes, isso porque com certeza cada um veio de um lugar. Mas voltanto as tabelas, neste caso teriamos a tabela de pedido com a data de pedido, e a tabela de itens que é relacionada ao pedido e contem a data de entrega de cada item. Podemos dizer que a data de entrega sempre estara bem próxima a data de pedido. Isso representa claramente uma relação entre a data de pedido e a data de entrega. Após entendido isto, vamos voltar a otimização. Se você tiver uma consulta onde faz um join entre a tabela de Pedido e Itens fazendo filtro por uma das datas, o SQL Server pode alterar sua consulta a fim de otimiza-la sem você saber disso. Como?… vamos começar com os exemplos. Primeiro vamos criar uma estrutura de tabelas parecidas com o cenário mencionado acima. IF OBJECT_ID('Pedidos') IS NOT NULL DECLARE @i Integer WHILE @i < 10000 INSERT INTO Itens(ID_Pedido, ID_Produto, Data_Entrega, Quantidade) Após criar as tabelas, teremos uma estrutura parecida com o cenário que mencionei, vamos ver os dados de um pedido. Agora vamos supor que a seguinte consulta seja construida. SELECT * Traduzindo, eu quero todos os dados de Pedidos e Itens vendidos entre 01/03/2009 até 05/03/2009. Para esta consulta o SQL Server criou o seguinte plano de execução: SELECT * FROM Pedidos INNER JOIN Itens ON Pedidos.ID_Pedido = Itens.ID_Pedido WHERE Pedidos.Data_Pedido BETWEEN '20090301' AND '20090305' No plano em modo texto, podemos facilmente perceber que o filtro especificado no where, foi aplicado durante a leitura do índice xpk_Pedidos e o campo que recebeu o filtro foi justamente o Data_Pedido espeficidado no where. A primeira coisa que poderiamos fazer para otimizar esta consulta, seria criar um indice na coluna Data_Pedido. Ok, você pode estar pensando, a isso eu sei, isso todo mundo faria logo de cara, você esta certo, mas vamos fazer isso e continuar na otimização. CREATE INDEX ix_teste ON Pedidos(Data_Pedido) INCLUDE(Valor) Após criar o índice temos o seguinte plano: SELECT * FROM Pedidos INNER JOIN Itens ON Pedidos.ID_Pedido = Itens.ID_Pedido WHERE Pedidos.Data_Pedido BETWEEN '20090301' AND '20090305' Agora a coisa melhorou um pouco, ao invés de fazer um Clustered Index Scan para ler os dados da tabela Pedidos, o SQL fez um Index Seek baseado no índice que acabamos de criar. Ok o que mais podemos fazer? Vamos começar a ver o Correlation_Optimization. Vemos que existe um gargalo para ler os dados da tabela Itens, segundo o plano de execução que temos, esta leitura representa 49% de custo da consulta, e ele esta fazendo um Scan, será que da pra fazer um Seek? Conhecendo o banco de dados e a estrutura das tabelas e negócio, poderiamos alterar a consulta para incluir um filtro na tabela Itens. Mas para isso teremos que ter certeza de que nosso filtro não irá causar uma mudança no resultado dos dados. Uma alternativa seria a seguinte:
Com isso teriamos a seguinte consulta: SELECT * Desta forma eu conseguiria forçar um filtro na tabela Itens, veja o plano: Mas pergunta? Como fazer para descobrir os valores do item 1, sozinho? Porque normalmente os valores do between são variáveis e não fixos. Que tal deixar o SQL se virar por você? , Basta habilitar o DATE_CORRELATION_OPTIMIZATION que ele identifica isso pra você, e aplica o filtro no Data_Entrega sozinho, óia que esperto eim! Vamos ver se é verdade…. ALTER DATABASE <NomeDoSeuBanco> SET DATE_CORRELATION_OPTIMIZATION ON; Vamos rodar a consulta denovo… SELECT * FROM Pedidos INNER JOIN Itens ON Pedidos.ID_Pedido = Itens.ID_Pedido WHERE Pedidos.Data_Pedido BETWEEN '20090301' AND '20090305' Repare que desta vez, mesmo sem eu colocar o filtro na coluna Data_Entrega o SQL colocou este filtro pra mim. Conclusão O DATE_CORRELATION_OPTIMIZATION é uma feature muito boa mas que merece uma analise mais detalhada de onde pode ser utilizada, ela também exige que algumas regras sejam atendidas para que funcione. Por exemplo:
Bom galera, fica ai a dica… Abraço Comments (1)
TrackbacksThe trackback URL for this entry is: http://fabianosqlserver.spaces.live.com/blog/cns!52EFF7477E74CAA6!1639.trak Weblogs that reference this entry
|
|
|