Olá, pessoal! Veremos aqui um pouco mais sobre performance em consultas com o plano de execução do SQL Server, além de algumas dicas de utilização da cláusula WHERE.
Ao
executarmos uma consulta, normalmente não nos preocupamos como o SQL
recebe e trata essas requisições. Para todo processo repassado ao SQL por
intermédio de uma query, é criado um plano de execução. Esse plano de execução não faz nada mais que alocar em cache a consulta para uso “futuro-breve”.
Vamos ao exemplo:
Supondo que eu precise executar uma consulta básica em minha tabela tbTeste:
SELECT id, nome, nascimento FROM tbTeste WHERE id = 10
Ao executar esta consulta, é criado um plano de execução em background, portando, se executar novamente o mesmo select, meu retorno será mais rápido.
Supondo
que eu necessite rodar novamente o mesmo select, mas alterando minha
clausula WHERE, o plano de execução criado anteriormente já não
servirá mais, pois o SQL interpreta como sendo um novo comando e,
consecutivamente, o plano de execução é criado novamente e armazenado em cache.
Para ganharmos um pouco mais de performance neste pequeno script, necessitaremos fazer um pouco mais do uso da linguagem T-SQL. Exemplo:
DECLARE @id AS INT
SET @id = 10
SELECT id, nome, nascimento FROM tbTeste WHERE id = @id
Ao
receber o comando pela primeira vez, é criado seu plano de execução e
automaticamente o SQL interpreta a variável como fazendo parte do
plano. Logo, sua consulta é armazenada e toda vez que você utilizar a
mesma query, ela será executada mais rápido, independente do valor de entrada da variável @id.
Em bases muito pequenas e com pouca concorrência, este simples procedimento pode não fazer muita diferença, em proporções maiores, esta pode ser considerada uma solução breve.
Dica:
Ao
executar uma consulta, informe ao SQL o nome dos campos que você
necessita ao invés do bom e velho ” * “, mesmo você precisando de todos
os campos da mesma, pois o SQL vai direto aos campos. Utilizando o ” * “, o SQL tem o trabalho de buscar as colunas em tabelas do sistema, para, depois, retornar o resultado de todas as colunas da tabela.
Existe
também um truque na cláusula WHERE que faz bastante diferença. Devemos
levar em consideração que nem sempre códigos curtos e uso de funções da
linguagem ajudam a turbinar nossas consultas.
Vamos ao exemplo:
SELECT nome FROM tbTeste
WHERE LOWER(nome) = 'rodrigo'
Esta consulta demora cerca de 2 vezes mais, que a seguir:
SELECT nome FROM tbTeste
WHERE nome = 'RODRIGO' OR nome = 'rodrigo'
Em alguns casos, onde existem muitos relacionamentos, o operador OR poderia ser trocado por UNION, pois o “nosso amigo OR” consome muita CPU ao realizar o processo lógico.
Outra ótima solução para a utilização de muitos OR em uma determinada
consulta seria o uso do operador IN e NOT IN ou EXISTS e NOT EXISTIS.
A diferença básica desses operadores seria que o IN você utiliza para
verificar valores e o EXISTS, para querys correlatas.
Exemplo de IN:
SELECT nome FROM tbTeste
WHERE nome IN ('rodrigo', 'RODRIGO')
Exemplo de EXISTS:
SELECT nome FROM tbTeste
WHERE EXISTS
(SELECT nome FROM tbTeste2 WHERE nome = 'rodrigo' OR nome = 'RODRIGO')
Utilizando nosso plano de execução e as dicas aqui explanadas teríamos scripts do tipo:
DECLARE
@nome AS VARCHAR(25),
@nomeLW AS VARCHAR(25),
@nomeUP AS VARCHAR(25)
SET @nome = 'Rodrigo'
SELECT @nomeLW = LOWER(@nome), @nomeUP = UPPER(@nome)
SELECT id, nome, nascimento
FROM tbTeste
WHERE nome IN(@nomeLW, @nomeUP)
Contudo, teremos um plano de execução que segue boas práticas para uma boa performance em suas consultas.
Vale a pena lembrar que o armazenamento de consultas em
procedures (SELECT, INSERT, UPDATE) também produz um excelente
resultado final na questão tempo de resposta. Assim como em nossas consultas, o plano de execução é criado ao compilarmos nossas Procedures.
Obrigado, pessoal, e até a próxima!