O documento discute otimização de consultas SQL. Ele aborda tópicos como analisar planos de execução, otimizar consultas, trabalhar corretamente com índices, melhores práticas na escrita de SQL e dicas para otimizar o desempenho do banco de dados.
O documento discute otimização de consultas SQL. Ele aborda tópicos como analisar planos de execução, otimizar consultas, trabalhar corretamente com índices, melhores práticas na escrita de SQL e dicas para otimizar o desempenho do banco de dados.
O documento discute otimização de consultas SQL. Ele aborda tópicos como analisar planos de execução, otimizar consultas, trabalhar corretamente com índices, melhores práticas na escrita de SQL e dicas para otimizar o desempenho do banco de dados.
Otimização de consultas; Trabalhando corretamente com índices; Melhores práticas na escrita de SQLs; Erros comuns que geram problemas de performance; Dicas para otimizar o desempenho do banco de dados e de consultas SQL a partir de aplicações (Delphi, C#, PHP etc).
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 2
Introdução
Problema: sistema criado inicialmente para um número
limitado de tarefas, que ao longo do tempo cresceu muito maior do que o esperado; Quando vários usuários utilizam simultaneamente o sistema, é quase impossível parar para otimizá-lo. Além disso, o aumento da capacidade de funcionamento de um servidor não pode resolver completamente o problema. Por isso, considere como passo inicial otimizar consultas SQL que consomem os maiores recursos.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 3
Plano de Execução
O SQL Server gera um plano de execução para cada
consulta. O plano descreve um algoritmo que vai conduzir a um resultado desejado. Para atingir a velocidade máxima de execução de consulta, do otimizador de consulta (“query optimizer”), sempre tente gerar um plano com a sequência de ações que consome recursos mínimos do servidor.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 4
Exemplo de geração de plano de execução
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 5
Exemplo de geração de plano de execução
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 6
Entendendo o plano de execução da consulta em detalhes
Cada ícone no gráfico do plano de execução representa um
item de ação (Operação). O plano de execução deve ser lido da direita para a esquerda, e cada item de ação tem uma porcentagem do custo em relação ao custo total de execução da consulta (100%);
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 7
Entendendo o plano de execução da consulta em detalhes
No exemplo, o primeiro ícone na parte direita representa
uma operação de "Clustered Index Scan" que significa ler todos os valores de índice de chave primária da tabela, o que que exige 100% do custo total de execução da consulta. O ícone mais à esquerda no gráfico representa uma operação SELECT (que requer apenas 0% do custo total de execução da consulta).
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 8
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 9 Entendendo o plano de execução da consulta em detalhes
Observe o "Query Cost" no plano de execução, ele tem
100% em relação ao custo total. Isso significa que, esta consulta em particular, tem custo de 100% entre todas as consultas realizadas, pois existe apenas uma consulta na instrução. Se houvesse várias consultas simultaneamente executadas, cada consulta teria seu próprio percentual de custo (menos de 100%). Clicando-se de direita no item do plano, pode-se obter mais detalhes, como na figura:
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 10
Entendendo o plano de execução da consulta em detalhes
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 11
Quais informações obtemos através dos planos de execução?
Sempre que alguma da sua consulta executa lentamente,
você pode visualizar o plano de execução estimado (e real se necessário) e pode identificar o item que está levando a maior quantidade de tempo (em termos de porcentagem) na consulta. Quando você começar a rever qualquer SQL para otimização, na maioria das vezes, a primeira coisa que você DEVE fazer é ver o plano de execução. Você provavelmente irá identificar rapidamente a área na instrução SQL que está criando o gargalo no SQL geral.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 12
Quais informações obtemos através dos planos de execução?
Table Scan: Ocorre quando a tabela correspondente não
tem um índice clusterizado. Muito provavelmente, a criação de um índice clusterizado ou desfragmentar o índice irá permitir que você se livre dele. Clustered Index Scan: Às vezes considerado equivalente a Table Scan. Ocorre quando um índice não-clusterizado em uma coluna não está disponível. Na maioria das vezes, a criação de um índice não-clusterizado irá permitir que você se livre dele.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 13
Quais informações obtemos através dos planos de execução?
Hash Join: Este é o JOIN que custa mais caro em consumo
de recursos para o banco de dados. Isto ocorre quando as colunas de junção entre duas tabelas não são indexadas. A criação de índices sobre essas colunas irá permitir que você se livre dele.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 14
Quais informações obtemos através dos planos de execução?
Nested Loops : A maioria dos casos, isso acontece quando
um índice não-clusterizado não inclui uma coluna que é usada na lista de colunas SELECT. Neste caso, para cada membro no índice da coluna não-clusterizada, o servidor de banco de dados tem que procurar no índice clusterizado para recuperar o outro valor da coluna especificada na lista SELECT. Criando um índice clusterizado irá permitir que você se livre dele .
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 15
Tipos de Índices (principais)
Clusterizado: No SQL Server os índices clusterizados são, de
certa forma, uma consideração crítica com relação a arquitetura global do banco de dados. Eles determinam a ordem lógica em que os dados são armazenados nas tabelas, que consiste dos dados reais que são paginados referentes às tabelas. Não-Clusterizado: São os índices armazenados separadamente da tabela e contém uma lista ordenada de referências para a própria tabela.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 16
Aplicar indexação adequada das colunas da tabela no BD
Alguns poderiam argumentar se a implementação de
indexação adequada deve ser o primeiro passo no processo de otimização de desempenho de um banco de dados. Prefira aplicar indexação corretamente no banco de dados, em primeiro lugar. Isso permitirá que você consiga o melhor desempenho possível no menor espaço de tempo em um sistema que já esteja em produção.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 17
Aplicar indexação adequada das colunas da tabela no BD Aplicando / criação de índices no banco de dados não vai exigir que você faça qualquer modificação no aplicativo (Delphi, C#, PHP), e portanto, não requer qualquer configuração e implantação. Claro, essa melhoria rápida no desempenho pode ser alcançada se você achar que a indexação não está feita corretamente no BD atual. No entanto, se a indexação já estiver feita, ainda é recomendado que você passe por esta etapa.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 18
Aplicar indexação adequada das colunas da tabela no BD
Certifique-se de que cada tabela em seu banco de dados tem
uma chave primária; Isso irá garantir que cada tabela tenha um índice clusterizado criado (e, portanto, as páginas correspondentes da tabela são fisicamente ordenados no disco de acordo com o campo de chave primária). Assim, qualquer operação de recuperação de dados da tabela com a chave primária, ou qualquer operação de classificação no campo de chave primária ou qualquer intervalo de valores de chave primária especificados na cláusula WHERE irá recuperar os dados da tabela muito rapidamente.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 19
Aplicar indexação adequada das colunas da tabela no BD
Crie índices não-clusterizados em colunas que são:
Frequentemente usadas nos critérios de pesquisa; Usadas para fazer JOINs com outras tabelas; Usadas como campos de chave estrangeira; De ter alta seletividade (coluna que retorna uma porcentagem baixa (0-5%) de linhas de um número total de linhas em um determinado valor); Usadas na cláusula ORDER BY;
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 20
Crie os índices apropriados
Suponha-se, neste processo, de ter criado um índice em uma
coluna de chave estrangeira (ProductID) nas vendas (SalesID, SalesDate, SalesPersonID, ProductID, Quantidade). Agora, assumindo que a coluna é uma coluna ProductID “altamente seletiva” (seleciona menos de 5% do número total de linhas usando qualquer valor ProductID nos critérios de pesquisa), qualquer consulta SELECT que lê os dados a partir desta tabela usando a coluna indexada (ProductID) na cláusula WHERE deve executar rapidamente.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 21
Crie os índices apropriados
Isso certamente executará mais rapidamente em comparação
com a situação em que nenhum índice é criado na coluna de chave estrangeira (ProductID), caso em que, uma varredura completa da tabela é feito (varredura de todas as páginas relacionadas na tabela para recuperar os dados desejados). Mas, ainda assim, há ainda margem para melhorar esta consulta.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 22
Crie os índices apropriados Vamos supor que a tabela de vendas contém 10.000 linhas, e o seguinte SQL seleciona 400 linhas (4% do total de linhas):
A tabela de vendas tem um índice não-clusterizado na coluna
ProductID. Por isso, "procura" a árvore de índice não clusterizado para encontrar a entrada que contém ProductID = 112. Para cada chave primária (400 aqui), o mecanismo do SQL Server "procura" na árvore de índice clusterizados para encontrar os locais reais de linhas na página correspondente.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 23
Desfragmente índices se ocorrer a fragmentação
Você criou todos os índices apropriados em suas tabelas. Ou,
pode ser que os índices já estejam lá em suas tabelas de banco de dados. Mas você não pode ainda obter o bom desempenho desejado de acordo com suas expectativas. Há uma forte probabilidade de que a fragmentação do índice ocorreu. O que é a fragmentação do índice ?
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 24
O que é fragmentação de índice?
Situação onde as páginas de índice se dividem devido à
várias inserções de dados, atualizações e exclusões em tabelas no banco de dados. Se índices têm alta fragmentação, as varreduras / buscas nos índices levam muito tempo, ou os índices não são usados em todas as consultas (resultando em varredura total da tabela “Table Scan”). Assim , as operações de recuperação de dados executam lentamente.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 25
Como desfragmentar índices?
Você pode fazer isso de duas maneiras:
Reorganizando os índices fragmentados:
Reconstruindo índices:
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 26
Boas práticas em SQL
Movendo SQL da aplicação e implementá-las usando stored
procedures / views / funções / Triggers lhe permitirá eliminar qualquer SQL duplicado em sua aplicação. Isso também irá garantir reutilização de seus códigos SQL. A aplicação de todas SQL usando objetos de banco de dados irá permitir-lhe analisar as SQLs com mais facilidade para encontrar possíveis códigos ineficientes que são responsáveis pelo desempenho lento. Além disso, este permitirá que você gerencie seus códigos SQL de um ponto central.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 27
Boas práticas em SQL
Não use "SELECT *" em uma consulta SQL
Colunas desnecessárias acrescentam despesas com o tempo de recuperação de dados. O motor de banco de dados pode não utilizar índice de forma correta e, portanto, a consulta executa lentamente.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 28
Boas práticas em SQL
Evite colunas desnecessárias na lista SELECT e tabelas
desnecessárias em condições de junção (JOIN). Selecionando colunas desnecessárias em uma consulta SELECT adiciona sobrecarga para a consulta real, especialmente se as colunas desnecessárias são de tipos LOB. Incluindo tabelas desnecessárias em condições de junção (JOIN) força o mecanismo de banco de dados a recuperar e buscar dados desnecessários e aumenta o tempo de execução da consulta.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 29
Boas práticas em SQL
Não use o COUNT () agregado em uma subconsulta para
fazer uma verificação de existência Não use:
Em vez disso, use:
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 30
Boas práticas em SQL
Tente evitar JOINs entre duas colunas de tipos diferentes
Quando um JOIN é feito entre duas colunas de diferentes tipos de dados, uma das colunas deve ser convertido para o tipo do outro. Se você estão se juntando tabelas com tipos incompatíveis, um deles pode usar um índice, mas o otimizador de consulta não pode escolher um índice na coluna que ele converte.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 31
Boas práticas em SQL
Tente evitar dead-locks
Sempre acesse tabelas na mesma ordem em todos as suas stored procedures e triggers. Mantenha suas transações tão curtas quanto possível. Modifique poucos dados tanto quanto possível durante uma transação. Nunca, jamais espere a entrada do usuário no meio de uma transação.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 32
Boas práticas em SQL
Tente não usar COUNT (*) para obter a contagem de
registros em uma tabela Para obter a contagem total de linhas em uma tabela, geralmente usamos a seguinte instrução SELECT:
Esta consulta irá executar uma varredura completa da tabela
para obter a contagem de linhas. A consulta a seguir não seria necessária uma varredura completa da tabela.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 33
Boas práticas em SQL
Tente evitar SQL dinâmico
SQL dinâmico é difícil de depurar e solucionar problemas. Se o usuário fornece a entrada para o SQL dinâmico, então há possibilidade de ataques de injeção SQL.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 34
Boas práticas em SQL
Tente evitar o uso de tabelas temporárias
A não ser que realmente necessário, tente evitar o uso de tabelas temporárias. Prefira usar “Table Variables” (variáveis do tipo tabela). Em 99% dos casos, as variáveis de tipo tabela residem na memória, por isso são muito mais rápidas. As tabelas temporárias residem no banco de dados “tempdb”. Assim, operar em tabelas temporárias requer comunicação com banco de dados e, portanto, será mais lento.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 35
Boas práticas em SQL
Em vez de busca com LIKE, use “Full Text Search” para
pesquisa de dados textual Full Text Search sempre superam pesquisas LIKE em performance. Permitirem implementar critérios complexos que não podem ser implementadas usando uma pesquisa LIKE, como a busca de uma única palavra ou frase, em busca de uma palavra ou frase perto de outro palavra ou frase, ou pesquisar sobre as sinônimos de uma palavra específica.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 36
Boas práticas em SQL
Tente usar “UNION” para implementar uma operação "OR"
Tente não usar "OR" em uma consulta. Em vez disso use “UNION" para combinar o conjunto de resultados de duas consultas distintas. Isto irá melhorar o desempenho da consulta.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 37
Boas práticas em SQL
Implementar uma estratégia de “Lazy Loading” para grandes
objetos Armazene colunas de objetos grandes (como VARCHAR (MAX), Imagem, Textos, BLOBs etc.) em uma tabela diferente do que a tabela principal, e coloque uma referência para o objeto grande na tabela principal. Recupere todos os principais dados da tabela em uma consulta, e se um objeto grande é necessário para ser carregado, recupere os dados de objeto grande da outra apenas quando é necessário (on-demand).
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 38
Boas práticas em SQL
Use VARCHAR(MAX), VARBINARY(MAX) e NVARCHAR(MAX)
No SQL Server 2000, uma linha não pode exceder 8.000 bytes de tamanho. Esta limitação deve-se ao 8 KB de tamanho de página interna do SQL Server. Então, para armazenar mais dados em uma única coluna, você precisará usar text, ntext ou tipos de dados BLOBs que são armazenados em uma coleção de 8 páginas de dados KB . Para resolver esse problema, use VARCHAR(MAX), NVARCHAR (MAX) e VARBINARY(MAX). Estes tipos de dados podem conter a mesma quantidade de dados e podem conter 2 GB, e eles são armazenados no mesmo tipo de páginas de dados usados para outros tipos de dados .
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 39
Boas práticas em SQL
Implemente as seguintes boas práticas em Stored Procedures
Não use "SP_xxx" como uma convenção de nomenclatura. Isso resulta em pesquisas adicionais de I / O, porque o sistema interno do SQL Server armazena nomes de stored procedures começando com "SP_". Usando "SP_xxx", como a convenção de nomeação também aumenta a possibilidade de entrar em conflito com um sistema existente Stored Procedure. Use a cláusula WITH RECOMPILE na instrução EXECUTE (primeira vez), quando houver mudanças na estrutura de índices (de modo que a versão compilada da stored procedure pode tirar vantagem dos índices recém-criados). Use valores de parâmetro padrão para o teste fácil (default).
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 40
Boas práticas em SQL
Implementar as seguintes boas práticas em Triggers
Tente evitar o uso de Triggers. Disparar um trigger e executar um evento é um processo caro. Nunca use triggers que podem ser implementadas usando Constraints. Não use o mesmo Trigger para diferentes eventos (INSERT, UPDATE, DELETE). Não use o código de transação dentro de um Trigger. O Trigger sempre é executado dentro do escopo transacional do código que o aciona.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 41
Boas práticas em SQL
Implementar as seguintes boas práticas em VIEWS
Utilize VIEWS para o SQLs complexas. É possível criar VIEWs indexadas. Não use VIEWs que recuperam dados de uma única tabela somente (que será uma sobrecarga desnecessária). Utilize VIEWS para escrever consultas que acessam colunas de várias tabelas.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 42
Boas práticas em SQL
Para as consultas SQL mais complicadas, procure usar
VIEWS, dependendo da situação, o servidor estará consumindo melhor o tempo para a leitura e análise de dados. VIEWS não devem ser usadas em tudo, mas elas devem ser usadas com sabedoria.
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 43
Boas práticas em SQL
Elimine a re-leitura de dados.
Normalmente, a re-leitura de dados é uma das operações que mais demandam recursos. É por isso que as consultas devem ser escritas de uma forma que permitam a leitura de dados em uma consulta apenas uma vez. O exemplo a seguir mostra um uma query que lê dados duas vezes;
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 44
Duas leituras da mesma tabela
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 45
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 46 Outras Dicas
Aplicação de técnicas de Database Refactoring (Refatoração
de Banco de Dados); Utilize o Database Engine Tuning Advisor (para ajudar na criação de índices e outros); Utilize recursos nativos dos engines de conexão, como ADO.NET, Pooling, drivers nativos, para maximar a performance; Minimize o número de conexões (observando o plano de execução);
SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 47