Cuidado ao escrever queries
Post dedicado ao meu irmão gêmeo Emanoel Carlos de Alencar, que está se esforçando pra entrar na área de banco. Infelizmente foi pro Oracle, quem sabe consigo puxá-lo para o “mundo” SQL Server.
Obs: Apenas uma brincadeira, os dois produtos são bons. Sempre temos que avaliar qual a real necessidade do cliente para poder sugerir uma solução que o atenda e que “entre” no seu bolso.
Ola galera. blz? Em um dos meus artigos anteriores eu mostrei como trocar o uso do NOT IN para o Left JOIN(Link), porém, porque fizemos isso? Qual Ganho de performance ?
Se você já executou as duas queries do artigo anterior com o plano de execução habilitado, você verá que o plano e o custo estimado de ambos são iguais. Vamos ver?
SELECT c.cod,c.nome FROM dbo.TB_CLIENTE c WHERE c.cod NOT IN(SELECT p.cod_cli FROM dbo.tb_pedido p) OPTION(RECOMPILE)
SELECT c.cod,c.nome, p.COD,p.COD_CLI FROM dbo.TB_CLIENTE c LEFT JOIN dbo.tb_pedido p ON c.cod = p.cod_cli
WHERE p.COD_CLI is null OPTION(RECOMPILE)
Thiago Que dizer que não ganhamos nada fazendo essa troca!?Não é assim! O que faz com que o SQL Server escolha quais operadores irão ser usados para acessar os dados, são as estatisticas das suas tabelas e também os indices. Neste post não irei entrar em detalhes, mas , se quiserem saber mais umas das otimas referências que temos no cenário brasileiro é o Fabiano Neves Amorim(Sabe tudo de QO). O objetivo deste post é mostrar que quando temos duas tabelas com quantidade insignificantes de registros, o SQL Server, pode escolher o mesmo plano, realizar um clustered index scan para obter o mesmo resultado e devolve-lo ao usuário. Isso foi visto no print anterior que com queries diferentes o SQL Server montou o mesmo plano. Mas se as tabelas existissem milhões de linhas e de pagina de dados, será que o SQL Server iria usar os mesmos operadores para devolver os dados? Vamos ver isso na pratica? O que iremos fazer é: atualizar as estatisticas do SQL Serve e executar novamente as duas queries.
–Atualiza as estatisticas da tabela TB_CLIENTE
UPDATE STATISTICS dbo.TB_CLIENTE WITH ROWCOUNT = 500000, PAGECOUNT = 200
–Atualiza as estatisticas da tabela TB_PEDIDO
UPDATE STATISTICS TB_PEDIDO WITH ROWCOUNT = 500000, PAGECOUNT = 200
Obs: Na verdade nos comandos acima estamos atualizando as estatisticas apenas para propositos de testes. Isso apenas mostra como é importante deixar as estatisticas sempre atualizadas dos nossos banco de dados.
SELECT c.cod,c.nome FROM dbo.TB_CLIENTE c WHERE c.cod NOT IN(SELECT p.cod_cli FROM dbo.tb_pedido p) OPTION(RECOMPILE)
SELECT c.cod,c.nome, p.COD,p.COD_CLI FROM dbo.TB_CLIENTE c LEFT JOIN dbo.tb_pedido p ON c.cod = p.cod_cli
WHERE p.COD_CLI is null OPTION(RECOMPILE)
Executando novamente as queries, podemos ver que a diferença entre o custo usado pelo plano de execução da query que utiliza o NOT IN é superior ao custo da query que usa o operador LEFT JOIN. Quando você está trabalhando com otimização de queries, sempre tente imaginar um cenário com muitas linhas, pois, banco de dados crescem. Uma vez ouvi o seguinte de um certo gestor que tive: “Essa aplicação, funcionava no começo! Porque agora está apresentando lentidão?”. Simples o banco de dados no inicio da aplicação tinha 20 MB de base de dados, hoje tem 130 GB. Então fica a dica, queries bem escritas + estatisticas atualizadas + indices corretos = Vida com Menos Stress
Espero ter ajudado
5 comentários
Show de bola o post Thiago, lutamos pelas boas práticas!!!
Muito bom!
[…] Cuidado ao escrever queries […]
[…] Cuidado ao escrever queries […]
[…] Cuidado ao escrever queries […]