Como criar consultas SQL mais rápidas

setembro 29, 2007

Estou abordando este assunto aqui no blog, pelo fato de ser um assunto muito importante atualmente para organizações que possuem uma grande quantidade de dados e muitos acessos simultaneamente.

Uma consulta mal projetada pode acarretar em lentidão ao servidor ou até mesmo fazer com que o servidor permaneça fora do ar por um período, impossibilitando o usuário de utilizar algum serviço do sistema ou site, gerando prejuízo a organização.

Otimizar uma consulta SQL nem sempre é uma tarefa fácil e simples, precisa um pouco de conhecimento para desenvolver filtros que obtenham resultados que não custe ao servidor muitos recursos de hardware. Muitos dos exemplos que irei demonstrar foram resultados de pesquisas e testes executados no próprio Query Analyser do MS SQL Server 2000.

Uma forma de prejudicar bastante o desempenho ao acessar a base de dados, é a criação de TRIGGERS. Esta instrução é acionada sempre que uma determinada tabela sofre alguma alteração (INSERT, UPDATE, DELETE). Portanto, ao invés de criar uma ‘TRIGGER prefira criar uma PROCEDURE que será acionada sempre que uma tarefa for feita.

Ao criar um simples filtro em uma tabela, pode-se encontrar alguns pontos que prejudicam a performance da consulta. A consulta abaixo demonstra um dos exemplos:

SELECT

*

FROM

Cliente

Ao fazer algum filtro em uma tabela, evite informar todos os campos de uma tabela em uma consulta, a menos que isso for realmente necessário. Muitas das vezes não será utilizado todos os campos. A consulta acima pode ser executada rapidamente se a tabela da base de dados contiver poucos registros, mas para adquirir uma melhor performance da consulta é recomendável filtrar apenas os campos que serão utilizados, o exemplo abaixo demonstra um cenário parecido:

SELECT

Nome,

CPF,

RG,

Endereco

FROM

Cliente

Outro ponto importante é a utilização da instrução COUNT, esta instrução informa a quantidade de registros retornados em uma consulta.

SELECT

COUNT(*)

FROM

Cliente

Porém não há a necessidade de utilização desta consulta, porque ao executá-la, será contado um registro de cada vez. Para isto existe as tabelas ‘sysobjects e ‘sysindexes‘. Com estas duas tabelas é possível obter muitas informações de diversos todos objetos existentes na base de dados.

SELECT

sysobjects.name AS [Nome da Tabela],

sysindexes.rowcnt AS [Qtde. de Registros]

FROM

sysobjects

INNER JOIN

sysindexes ON

sysindexes.id = sysobjects.id

WHERE

sysobjects.name = ‘Cliente’

AND

sysindexes.indid = 1

A consulta acima informa a quantidade de registros existentes na tabela ‘Cliente’. Reparem que foi utilizado uma nova instrução, o INNER JOIN. Esta instrução serve para fazer a junção de duas ou mais tabelas, lembrando que isto significa que DEVE possuir algum registro na tabela secundária, ou seja na tabela que está recebendo o INNER JOIN, sendo assim, é necessário fazer a comparação de campos em comum que as duas possuem. Certifique-se que o nome da tabela escrito na cláusula WHERE está correto, caso contrário não será retornado nenhum registro. Esta consulta é outro exemplo que poderá trazer problemas de performance, porque ao utilizá-la, a consulta toda pode acessar qualquer uma das informações (campos) existentes nas tabelas. Uma outra forma de consultar a quantidade de registros de uma tabela é a seguinte:

SELECT

sysindexes.rowcnt AS [Qtde. de Registros]

FROM

sysindexes

WHERE

sysindexes.indid = 1

AND

EXISTS(

SELECT

sysobjects.id

FROM

sysobjects

WHERE

sysobjects.id = sysindexes.id

AND

sysobjects.name = ‘Cliente’

)

Ao fazer um filtro como o acima, pode-se obter resultados muito eficazes em relação ao desempenho. A instrução EXISTS é uma instrução extremamente rápida porque utiliza pouco recurso de hardware. É como se retornasse uma variável booleana.

Outra instrução que consome um maior processamento é a instrução IN, que é utilizada quando é necessário fazer o filtro de um vetor de dados. O exemplo abaixo informa os todos clientes que possuir algum telefone.

SELECT

Nome

FROM

Cliente

WHERE

ID IN(SELECT ClienteID FROM Telefone)

Outra maneira de informar estes registro seria utilizar (novamente) a instrução EXISTS ao invés da instrução IN.

SELECT

Cliente.Nome

FROM

Cliente

WHERE

EXISTS(

SELECT

Telefone.ClienteID

FROM

Telefone

WHERE

Telefone.ClienteID = Cliente.ID

)

São inúmeras as tarefas que se pode fazer para melhorar a performance de uma consulta. Estas são apenas algumas operações que devem ser feitas caso necessita de resultados mais rápidos em consultas SQL.

Vou ficando por aqui, deixe sua crítica, dúvidas ou sugestões referente ao artigo. Até a próxima.

13 Respostas to “Como criar consultas SQL mais rápidas”

  1. Ricardo Says:

    Dah hora Garni.
    Tinha coisa aê que eu naum sabia.
    Bora enche isso de atigo desse tipo.

    Flws

  2. Rosimar alexandre Says:

    eu li as suas dicas e acho que mandou bem principalmente ao leitor que esta começando sem experiencia.
    valeu continue postando
    obrigado

  3. tIAGO Says:

    select distinct substring(loca_id,1,5) as equip from tbfluxo_equip
    order by substring(loca_id,1,5) asc

    cara eu tenho esssa consulta que esta demorando 00:53:00 pra ser retornado os dados tem alguma maneira de otimiza-la ?? aguardo..

  4. Ronaldo Says:

    Parabéns, muito obrigado em nome de muitos que usaram essas dicas para facilitar seus trabalhos, mas como disse o Ricardo, quando tiver tempo e quizer mandar mais, será sempre bem vinda. abs.

  5. Alex Munhoz Says:

    Ola Amigo belo exemplo, parabéns pela forma que abordou as consultas. aguardamos novos posts. abração.

  6. Jhony Says:

    Muito bom.
    Parabens pelo trabalho.
    Gostaría de ajudar no neste blog, se houver interesse contacte-me.

  7. Flávio Lucena Says:

    Caro amigo, considerei muito interessante a dica de se utilizar os dados das tabelas sysobjects e sysindexes para se obter a quantidade de registros de uma tabela, mas o que fazer quando o resultado obtido através de select count(*) é superior do que o retornado pelo conteúdo do campo sysindexes.rowcnt ?

    Um abraço,

    Flávio Lucena

  8. Cristiana Mendes Says:

    Muito obrigada, as suas instruções são ótimas!!!!

  9. Luciana Says:

    Parabens, me ajudou muito.

  10. tiago Says:

    Parabéns amigo são iniciativas como esta que enrriquecem a area de desenvolvimento de software

  11. jose julio Says:

    Coisa simples e inteligente me tirou muitas duvidas, parabens!

  12. Sander Luiz Carlos Says:

    Caro amigo
    Lendo alguns de seus exemplos fiquei tentado a importuna-lo.

    preciso ter o retorno de dados entre duas tabelas

    a primeira se chama agenda
    a segunda se chama nhluciano

    preciso do resultado de horas do campo nhluciano que não constam na agenda.

    ja fiz de varia formas mas todas são lentas.

    Agradeceria muito a ajuda.
    Abraços
    Samder

  13. Marcus Says:

    Obrigado! Aparentemente, utilizando o EXISTS numa consulta aqui ao inves do IN, reduziu o tempo da minha consulta de 103 para 5 segundos!


Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: