Cuidado ao escrever queries

Cuidado ao escrever queries

Tempo de leitura: 3 minutos

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

  1. Show de bola o post Thiago, lutamos pelas boas práticas!!!

Deixe uma resposta

%d blogueiros gostam disto: