Você está na página 1de 48

SQL Tunning

Otimizando o acesso a dados, performance e


escrita de instruções SQL

Prof. Guinther Pauli

1
Overview

 Analisando planos de execução;


 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


Contato
http://www.facebook.com/guintherpauli
http://www.twitter.com/guintherpauli
http://www.gpauli.com
guintherpauli@gmail.com
http://guintherpauli.blogspot.com
guinther.pauli
guintherpauli@gmail.com

SQL Tuning - Guinther Pauli – guintherpauli@gmail.com 48

Você também pode gostar