Escolar Documentos
Profissional Documentos
Cultura Documentos
ESTUDO DE CASO
Dezembro de 2010
Itatiba / SP
ii
Mariana Gava
ESTUDO DE CASO
Dezembro de 2010
Itatiba / SP
iii
AGRADECIMENTOS
RESUMO
Bancos de dados tornam-se cada dia mais importantes no cotidiano da sociedade atual.
Durante as atividades diárias, pessoas deparam-se interações com algum banco de dados,
embora na maioria das vezes sem ao menos perceberem tal feito. Pode-se afirmar que os
bancos de dados são amplamente utilizados em diversas aplicações presentes no dia-a-dia,
tais como: transações bancárias, transações com cartão de crédito, reservas de linhas
aéreas e informações de horários, reservas de hotel, vendas, revendedores on-line, dentre
outras aplicações. Devido ao grande volume de dados que estes precisam gerenciar e a
complexidade de suas aplicações, é fundamental que as operações sejam realizadas de
forma eficiente, pois o desempenho de um Sistema de Gerenciamento de Banco de Dados é
medido a partir da sua eficiência na realização de consultas e alterações. Através de uma
linguagem de manipulação de dados (DML) os dados são manipulados dentro do SGBD,
sendo possível realizar diferentes funções como, consultas, atualizações e fornecer
relatórios específicos. SGBDs têm como principal função proteger o banco de dados contra
ataques maliciosos ou acessos não autorizados e também precisam garantir que não haja
mau funcionamento ou falhas que podem ocorrer no hardware ou software. Outra função
importante é quanto à manutenção dos dados. Bancos de dados precisam estar protegidos
com relação a danos causados pelos usuários, quer sejam intencionais ou não. Visando a
agilidade na consulta desses dados, o objetivo deste trabalho é analisar as técnicas de
otimização e tuning de banco de dados, utilizando o banco de dados SQL SERVER 2008,
pois a seleção de uma boa estratégia faz toda diferença e, em termos do tempo de
avaliação, a diferença de custo pode chegar a várias ordens de grandeza.
ABSTRACT
Databases become increasingly important in the daily lot of society today. During the daily
activities, people are faced with some interaction with a database, although most often
without even realizing it done. It can be stated that databases are widely used in various
applications present on the day to day, such as: banking transactions, credit card
transactions, airline reservations and information on schedules, hotel reservations, sales,
online retailers, among other applications. Due to the large volume of data they need to
manage complexity and its applications, it is essential that operations are carried out
efficiently, because the performance of a Management System Database is measured from
its efficiency in carrying out consultations and changes. Through a data manipulation
language (DML) data are handled within the SGBD, and can perform different functions such
as queries, updates, and provide specific reports. SGBDs have the main function to protect
the database from malicious attacks or unauthorized access and must also ensure that no
malfunctions or failures that may occur in hardware or software. Another important function is
for the maintenance of the data. Databases must be protected against damage caused by
users, whether intentional or not. Aiming to speed up the consultation of such data, the
objective is to analyze the techniques of optimization and tuning database using the
database SQL SERVER 2008, because the selection of a good strategy makes all the
difference and in terms of time evaluation, the difference in cost can reach several orders of
magnitude.
SUMÁRIO
7.2.3 Facilitando a captura do plano de execução usando SQL SERVER Profiler ................... 51
7.2.4 Eventos do plano de execução ....................................................................................... 52
7.3 Um pouco mais sobre planos gráficos ............................................................................... 53
8. ESTUDO DE CASO............................................................................................................. 66
8.1 O SGBD............................................................................................................................. 66
8.1.2 Infraestrutura .................................................................................................................. 66
8.2 Aplicação da metodologia .................................................................................................. 66
8.2.1 Base de dados................................................................................................................ 67
8.2.2 Implementação das consultas......................................................................................... 67
8.3 Testes................................................................................................................................ 67
8.3.1 Teste 1 (subconsultas aninhadas – comandos EXISTS e INNER JOIN) ......................... 67
8.3.2 Teste 2 (Transformando expressões NOT em expressões afirmativas) .......................... 69
8.3.3 Teste 3 (Usando ou não índices) .................................................................................... 71
9. ANÁLISE DOS RESULTADOS ........................................................................................... 75
10. CONSIDERAÇÕES FINAIS............................................................................................... 77
REFERÊNCIAS BIBLIOGRÁFICAS........................................................................................ 78
viii
LISTA DE SIGLAS
LISTA DE FIGURAS
LISTA DE TABELAS
1. INTRODUÇÃO
Atualmente banco de dados tornou-se peça fundamental nas atividades diárias das
pessoas. Muitas vezes nos deparamos com banco de dados nas nossas tarefas diárias e
nem ao menos sabemos disso. Alguns exemplos são: transações bancárias, transações
com cartão de créditos, reservas de passagens áreas, reserva de hotéis, compras on-line,
dentro outras aplicações.
Segundo uma das definições de Elmasri e Navathe, “Um banco de dados é projetado,
construído e povoado por dados, atendendo a uma proposta específica. Possui um grupo de
usuários definido e algumas aplicações preconcebidas, de acordo com o interesse desse
grupo de usuários.” (2005, p.4)
De acordo com Elmasri e Navathe (2005, p.4), “Um SGBD é uma coleção de
programas que permite aos usuários criar e manter um banco de dados.” Sendo assim, um
banco de dados é construído através de dados que são armazenados e assim são
controlados por um SGBD.
SGBDs têm como principal função proteger o banco de dados contra ataques
maliciosos ou acessos não autorizados e também precisam garantir que não haja mau
funcionamento ou falhas que podem ocorrer no hardware ou software. Outra função
importante é quanto à manutenção dos dados. Bancos de dados precisam estar protegidos
com relação aos danos causados pelos usuários, quer sejam intencionais ou não.
1.1 Objetivos
Como citado anteriormente, um banco de dados relacional é formado por uma coleção
de tabelas, sendo que cada tabela possui um nome único. A relação entre um conjunto de
valores é representada pela linha de uma tabela.
15
No início da década de 1970, a IBM desenvolveu a versão original da SQL, a qual foi
chamada de Sequel. Após anos de evolução, passou a ser chamada de SQL (Structure
Query Language), tornando-se a linguagem padrão de banco de dados relacional.
Em 1986, foi publicado um padrão SQL chamado de SQL-86 pelo American National
Standards Institute (ANSI) e a International Organization for Standardization (ISO). Em 1989,
o ANSI publicou o SQL-89 e depois surgiram as versões SQL-92 e SQL-1999. Atualmente a
versão utilizada é o SQL-2008. A linguagem SQL possui várias partes:
• Controle de transação: SQL inclui comandos que especificam o início e o fim das
transações.
16
• SQL embutida e SQL dinâmica: definem como as instruções SQL podem ser
incorporadas dentro das linguagens de programação.
A SQL usa os termos tabela, linha e coluna, ao invés de relação, tabela e atributo para
o modelo relacional formal. De acordo com Elmasri e Navathe (2005), o principal comando
SQL para definição de dados é o CREATE, que pode ser usado para criar esquemas,
tabelas (relações) e domínios da mesma forma que outros construtores, como visões
(views), asserções (assertions) e gatilhos (triggers).
O padrão SQL SERVER 2008 aceita diversos tipos de domínio internos, como:
Tipos numéricos:
Tipo BIT:
Tipo data:
Tipos caracteres:
Por padrão todo caracter ocupa um byte. Se considerarmos que um byte representa
um octeto de oito bits e que cada bit tem duas possibilidades (ligado ou desligado), então
um byte pode representar 256 possibilidades (2^8). No passado, 256 possibilidades eram
suficientes para cobrir todo o conjunto de caracteres americano.
19
Além da busca ser realizada pelo sistema de uma maneira mais eficiente para
executar uma consulta, através de uma expressão similar na álgebra relacional, outros
aspectos também são observados tais como: algoritmos para execução de operações e
também índices específicos que serão utilizados.
Existem diversas maneiras de uma consulta ser expressa, com diferentes custos de
avaliação. É bom ressaltar que, a ordem das tabelas é irrelevante, desde que seja
equivalente o conjunto de tabelas.
21
Em primeiro lugar, uma consulta SQL é traduzida para uma expressão equivalente na
álgebra relacional, sendo representada por uma estrutura de dados de árvore de consulta,
que após é otimizada. Uma regra de equivalência diz que expressões de duas formas são
equivalentes. É através delas que o otimizador transforma expressões em outras
logicamente equivalentes.
Sendo assim, consultas aninhadas dentro de uma consulta são identificadas como
blocos separados.
Também é importante o mais cedo possível manter apenas os atributos necessários para as
operações subseqüentes nas relações intermediárias, por meio da inclusão de operações
Project (π).
• Custo de armazenamento: custo de arquivos temporários que são gerados por uma
estratégia de execução de consulta.
• Custo do uso de memória: custo referente ao número de buffers de memória que são
solicitados durante a execução da consulta.
Para uma consulta complexa o número de planos de consulta diferentes que são
equivalentes pode ser muito grande. Várias técnicas são utilizadas para reduzir ainda mais o
custo da pesquisa por uma grande quantidade de planos. Para Silberschatz (2006, p.395),
No SQL SERVER, subconsultas são consultas aninhadas, que pode ser utilizada em
SELECT, INSERT, UPDATE ou DELETE, ou mesmo em subconsulta. Existem dois tipos de
subsconsultas aninhadas: Correlacionada e não correlacionada.
Demais exemplos:
Comando IN
O mesmo exemplo que o acima, mas usando o JOIN ao invés do IN. A diferença é
que com o JOIN, consegue-se pegar os campos das duas tabelas e usar no SELECT, já
com o IN isso não é possível.
SELECT Name
FROM Production.Product
WHERE ProductSubcategoryID NOT IN ( SELECT ProductSubcategoryID FROM
Production.ProductSubcategory WHERE Name = 'Mountain Bikes' )
28
SISTEMAS RELACIONAIS
• Como evitar excessivas disputas por bloqueios, para que não ocorra a concorrência
entre as transações;
29
• De que maneira alocar recursos, como discos, RAM e também processos para que
haja uma utilização mais eficiente;
De acordo com Elmasri e Navathe, “Se um dado projeto físico de banco de dados não
atinge os objetivos esperados, podemos voltar ao projeto lógico do banco de dados, fazer
ajustes no esquema lógico e remapeá-lo num novo conjunto de tabelas e índices físicos”.
(2005, p. 390).
• Atributo(s) de uma tabela pode(m) ser repetido(s) em outra mesmo que isso crie
redundância e uma anomalia potencial;
• Algumas cláusulas DISTINCT podem ser redundantes e podem ser evitadas sem a
modificação do resultado, pois ele causa uma operação de ordenação e deve ser
evitado sempre que possível.
• O uso desnecessário de tabelas de resultado temporário pode ser evitado por meio
da aglutinação de múltiplas consultas em uma única consulta, a menos que a relação
temporária seja necessária para algum processamento intermediário. Em algumas
situações que envolvem o uso de consultas correlacionadas, os temporários são
úteis;
alterar a ordem de forma que a menor das relações seja varrida e a maior relação
usada como um índice adequado;
A causa do baixo desempenho pode estar relacionada ao hardware, que inclui a rede
disponível, processador, memória RAM, entre outros, ou também nos softwares. Esses
problemas geram gargalos que interferem no bom desempenho do banco de dados.
Quando se trata de banco de dados relacional as causas de baixo desempenho
também podem estar relacionadas a(o):
a) Sistema operacional (SO), por razões de má parametrização;
b) SGBD relacional, relacionada às inadequadas configurações nas áreas de buffers,
organização do logging, alocação de arquivos, entre outros;
c) Rede, devido a impactos no tráfego em razão de processamento de dados
efetuados no servidor ou na rede;
d) Modelo físico de dados, por razão de inadequação na definição da estrutura das
tabelas e índices;
e) Aplicação, com relação a problemas na estrutura lógica efetuada pelo
programador, o que compreende a linguagem hospedeira e os comandos em SQL
SERVER.
De acordo com Mullins (2005), “Quase 80% dos problemas de performance em banco
de dados são causados por códigos SQL mal elaborados”. Reduzir o tempo dos SQL e o
custo é importantíssimo para que uma grande parte dos problemas seja reduzida.
De acordo com Couto (2006), existem algumas observações a serem feitas para
aumentar a performance do banco de dados, como:
Couto (2006), ainda explica em seu artigo que a metodologia de tuning de SQL
envolve identificar as queries que consomem mais recursos para então otimizá-las.
Geralmente, um número pequeno de queries é responsável pela maior parte das atividades
que ocorrem no banco de dados. É essencial que se tente entender por completo a
aplicação, focando a atenção nos SQL ou tabelas onde os benefícios do tuning excederão
os custos. Devem-se observar alguns passos:
• Otimizar primeiro os SQL mais críticos, não perdendo tempo otimizando códigos que
raramente são utilizados;
• Utilizar índices, porém não criá-los em demasia. Alguns índices podem trazer um
resultado com efeito adverso no desempenho. O critério básico da escolha de
índices é a seletividade. Quando um banco de dados resolve uma consulta,
geralmente, ele precisa percorrer mais registros do que aqueles realmente
retomados pela consulta. Os registros percorridos que forem rejeitados representam
o trabalho perdido. Quanto menor for o trabalho perdido, mais perto estará da
performance ótima para resolver a consulta;
• Evitar full table scans se o resultado pode ser recuperado via índice, a menos que a
tabela seja pequena e o custo diminua. Quando a tabela é pequena, o trabalho
envolvido em acessar o índice, pegar o endereço e acessar a tabela é maior que o
esforço de ler a tabela inteira;
• Queries muito grandes devem ser divididas em queries menores. Lógicas complexas
de negócio no SQL devem ser evitadas;
• Evitar usar os comandos que produzem sort como: GROUP BY, ORDER BY,
DISTINCT, etc. No sort, o banco recupera todas as informações necessárias
primeiramente, para após realizar a ordenação;
• Substituir por junções os blocos SELECT embutidos utilizando IN, =ALL, =ANY e
=SOME;
• Se uma junção de igualdade for definida entre duas tabelas, o predicado de faixa
(condição de seleção) para o atributo de junção definido em uma tabela pode ser
repetido para a outra tabela;
35
Um índice torna rápida a recuperação de linhas de uma tabela, pois contém chaves de
uma ou mais colunas da tabela que são criadas e armazenadas em uma estrutura de
árvore. Desta maneira o SQL SERVER faz a associação dos valores de chave com as
linhas de pesquisa. Os índices podem ser:
Clustered: Através dos valores de chave é que esse tipo de índice classifica e
armazena suas linhas de dados. Por existir apenas um índice desse tipo em uma tabela, a
classificação das linhas de dados é feita em ordem única.
Quando a tabela não possui um índice clusterizado, seus dados ficam armazenados
numa estrutura denominada heap. Denomina-se heap porque os dados não têm uma ordem
lógica e são gravados nas páginas que tem espaço disponível. As páginas de dados não
são ligadas a uma lista vinculada. O espaço alocado para o heap é gerenciado pela coluna
de páginas Index Allocation Map (IAM). A movimentação pelo heap é feita pelo SQL
SERVER através das páginas IAM. Não existe vínculo entre as páginas de dados e as
linhas dentro delas.
Não Custerizado: Nesse tipo de índice a estrutura é diferente das linhas de dados,
pois possui um ponteiro que armazena o valor de chave do índice. O ponteiro de uma linha
de índice é denominado localizador de linhas.
Os dois tipos de índices podem ser exclusivos, garantindo que duas linhas não tenham
o mesmo valor que a chave do referido índice.
No SQL SERVER, os índices são organizados como árvores B. Pelo fato de ser
balanceada, a árvore B localiza qualquer registro, propiciando o rápido acesso aos dados
através da pesquisa de um valor-chave do índice.
36
Cada índice clusterizado, tem um particionamento único. Caso algum índice possua
particionamentos múltiplos, cada um terá uma estrutura de árvore B com os dados
específicos dele. Para cada particionamento usado pelo índice, os índices clusterizados tem
uma linha em sys.partions com índex_id = 1.
Fonte: http://www.batebyte.pr.gov.br/modules/conteudo/conteudo.php?conteudo=1184
37
Cada linha desse índice possui o valor de chave e um ponteiro que aponta para a linha
de dados no índice clusterizado ou no heap.
Fonte: http://www.batebyte.pr.gov.br/modules/conteudo/conteudo.php?conteudo=1184
38
índices?
No SQL SERVER existe uma ferramenta que auxilia na análise e seleção de índices
mais apropriados que é chamada de “Orientador de otimização do mecanismo de banco de
dados”.
O máximo de dados que uma linha suporta é 8.060 bytes (8KB), não incluindo os
dados armazenados em tabelas que possuem colunas varchar, nvarchar, varbinary ou
SQL_variant. Caso ocorra excesso de dados, o SQL SERVER move uma ou mais colunas
de comprimento variável para páginas na unidade chamada de ROW_OVERFLOW_DATA.
Se houver diminuição do tamanho da linha, através de uma operação subseqüente, o SQL
SERVER transportará novamente a coluna para a página de dados original.
• Mistas: Podem ser compartilhadas por até oito objetos, podendo cada página
pertencer a um objeto diferente;
Fonte: http://www.batebyte.pr.gov.br/modules/conteudo/conteudo.php?conteudo=1184
Gerencia o armazenamento de diferentes tipos de dados, tais como text, ntext, image,
xml, varchar(max), nvarchar(max), varbinary(max) e tipos de dados Common Language
Runtime (CLR) definidos pelo usuário.
• Certos índices podem estar causando sobrecarga excessiva, porque são baseados
em um atributo que sofre freqüentes alterações;
É através dos dados armazenados nas estatísticas das tabelas, referentes aos
registros das tabelas, que o SQL SERVER decide qual será o melhor plano de execução a
escolher. Desta maneira, é de suma importância manter as estatísticas sempre atualizadas,
pois do contrário, o otimizador não terá informações necessárias para aperfeiçoar
determinada consulta, gerando assim, um plano de execução com estimativas erradas.
Quando uma solicitação é feita e enviada ao servidor, a mesma é guiada por um plano de
execução, que se bem executado, trará o mais eficiente caminho da solicitação. O plano de
execução também auxilia na identificação qual parte do código SQL que está causando o
problema.
O plano de execução é composto por operadores que na maioria das vezes são
aplicados em certa ordem. É através do plano de execução, que se determina a ordem e
acesso das tabelas que estão envolvidas na query, quais índices que serão utilizados e
métodos para aplicá-los.
O otimizador do SQL gera diversos planos, mas escolhe o que apresenta melhor
performance, ou seja, o que apresenta o menor tempo para responder a consulta. Ele é
quem decide como os dados serão acessados, por meio de índices, os tipos de JOINs a
utilizar. É através de cálculos de custo, como processamento de CPU e operações de I/O,
gerados pelo plano de execução que determinará qual será o caminho mais rápido de
execução. É importante ressaltar que o custo estimado é apenas uma estimativa.
Em casos, onde é realizada uma consulta simples, o otimizador não perde tempo
tentando calcular o plano ideal, ele simplesmente aplica um plano trivial único a estes tipos
de procedimentos. Porém, se a consulta não é trivial, o otimizador realiza um custo base de
cálculo para selecionar um plano, baseado em estatísticas que são mantidas pelo SQL
SERVER. Porém, nem todas as possibilidades são avaliadas, pois o custo é muito alto e
desta forma compromete-se o ganho do desempenho. O plano de execução é determinado
através de testes com diferentes associações, reorganizando a ordem de junções, tentando
43
diferentes índices e assim sucessivamente até chegar ao que ele pensa ser o plano mais
rápido.
Geralmente, não existe diferença entre os dois planos, todavia algumas circunstâncias
causam diferenças, como:
O SQL SERVER oferece apenas um tipo de plano de execução, sendo três diferentes
formatos:
Planos gráficos: Oferecem uma maneira rápida e fácil de leitura, porém os dados
nesse tipo de plano ficam mascarados. Tanto o plano atual, como o estimado podem ser
vistos da mesma maneira.
A seguir, exemplos de Planos de Texto (TEXT plans) e Planos XML (XML plans):
45
Clicando no link gerado, o SQL direcionará para outra janela, na qual abrirá o plano de
execução no formato XML, conforme demonstra a figura abaixo:
Um plano de execução deve ser lido da direita para a esquerda e de cima para baixo.
Na figura abaixo, observa-se apenas que houve uma varredura de tabelas (table scan), no
qual se produziu um conjunto de resultados, representados através do comando SELECT. A
quantidade de dados que são passados na consulta, é o fator que representa a espessura
da seta, pois quanto mais grossa a linha, maior será a quantidade de dados. É possível
saber o número de linhas representado, passando o ponteiro do mouse sobre as flechas,
confirmando assim se o número apresentado está correto. Na figura 7.6 é possível
visualizar:
48
Abaixo de cada ícone exibi-se um número com uma porcentagem, que representa o
custo relativo à consulta para esse operador. Esse custo que é retornado pelo otimizador, é
o custo do tempo de execução para aquela determinada operação. No caso da consulta do
exemplo acima, o custo maior refere-se à operação “table scan”, que ocorre quando o
mecanismo de armazenamento é obrigado a ler linha por linha, retornando todas as
informações, pois nenhuma outra cláusula foi especificada, como a cláusula WHERE.
Entretanto, é importante ressaltar que como as porcentagens referem-se a razões e não
números reais, então mesmo um operador que tenha 0 % terá um pequeno custo associado.
Acima dos ícones é possível visualizar o custo de 100% que representa grande parte
da seqüência de consulta. Desta maneira, como cada consulta pode ter várias etapas, e
cada uma dessas etapas tem um custo em relação à consulta, é possível executar também
diversas consultas dentro de um lote e obter planos de execução para eles.
Passando o ponteiro do mouse sobre o ícone SELECT, observa-se os dados que são
apresentados na figura 7.7:
49
Os operadores lógicos compõem o resultado dos cálculos de otimização que são feitos
quando uma consulta é executada. Os operadores físicos representam o que de fato
ocorreu. Na maioria das vezes esses operadores sempre são parecidos.
SERVER Profiler
Uma ferramenta poderosa existente no SQL SERVER, é o SQL Profiler, que realiza a
captura de dados sobre eventos, tais como a execução de T-SQL ou então procedimentos
armazenados, que ocorrem dentro do SQL SERVER.
Essa ferramenta mostra como o SQL SERVER resolve consultas internas fornecendo
uma interface gráfica para a funcionalidade oferecida pelo Rastreamento SQL. Com o SQL
SERVER Profiler, é possível capturar atividades geradas por uma carga de trabalho em uma
instância do SQL SERVER. Através de modelos pré-definidos, os eventos que são
capturados e exibidos podem ser definidos, e assim podendo realizar a modificação de
modelos fornecidos pelo sistema para criar os seus próprios. A carga de trabalho, que
servirá para uma futura avaliação, também pode ser capturada em uma tabela ou um
arquivo. Rastreamentos podem ser iniciados a qualquer momento a partir do SQL SERVER
Management Studio, baseado em seu contexto de conexão. O comando Rastrear Consulta
no SQL SERVER Profiler, auxilia no rastreamento da execução de instruções em uma
determinada sessão do Editor de Consulta, usando o SPID da janela de consulta como um
filtro.
executar em certos momentos e em certos períodos. Tais vestígios podem ser visualizados
na tela ou enviados para um arquivo ou uma tabela em um banco de dados.
• Showplan All para compilação de consulta: Esse evento possui os mesmos dados
que o Showplan All event, mas apenas dispara quando ocorre a compilação da
consulta.
53
• Showplan Statistics Profile: Esse evento refere-se ao plano de execução real e utiliza
o comando STATISTICS PROFILE.
• Showplan XML para compilação de consulta: Igual ao Showplan XML acima, porém
só dispara quando alguma consulta está sendo compilada.
• Showplan XML Statistics Profile: Esse evento gera o plano atual para cada consulta
executada.
Alguns operadores, como os de ordenação (sort), hash, match e junção de join exigem
uma quantidade variável de memória para executar e por causa disso, consultas com esses
operadores podem ter que aguardar por memória disponível antes da execução, podendo
assim afetar o desempenho. A maioria dos operadores comporta-se de duas maneiras
distintas: bloqueio e sem bloqueio. Um operador de bloqueio precisa para produzir sua
saída, obter todos os dados. Esse tipo de operador pode contribuir significativamente para
problemas de concorrência, prejudicando assim o desempenho. Já o operador sem bloqueio
recebe a entrada e ao mesmo tempo cria a saída.
Às vezes, quando ocorre um index scan, é preciso saber se o plano de execução está
retornando mais linhas do que realmente é necessário. Desta maneira, há necessidade de
um fino ajuste na consulta utilizando a cláusula WHERE, para que assim o plano retorne
apenas as linhas que realmente são necessárias, pois caso contrário, ocorrerá o desperdício
de recursos do SQL SERVER, prejudicando o desempenho geral.
55
Índices seek são totalmente diferentes dos índices scan, que percorrem linha a linha
para encontrar os dados que a consulta solicita. Um índice seek, clustered ou não, ocorre
quando o otimizador é capaz de localizar um índice que pode ser usado para recuperar os
dados feitos na solicitação da consulta. Sendo assim, o mecanismo de armazenamento
recebe a ordem para procurar os valores com base nas chaves do índice determinado. É
possível verificar nesse exemplo do índice seek, que a propriedade ORDERED agora é
verdadeira, indicando que os dados foram ordenados pelo otimizador.
56
Como nos índices clustered, um índice nonclustered utiliza um índice para realizar a
busca de linhas a serem devolvidas. Esse tipo de índice acontece quando todos os dados se
encontram nele.
57
Conforme se observa esse plano envolve mais que uma única operação. Como dito
anteriormente, o plano deve ser lido da direita para a esquerda e de cima para baixo. A
primeira operação é relacionada a um índice seek, que não é um índice non-unique, non-
clustered e non-covering. Um índice non-covering é um índice que não retorna todos os
dados necessários para uma consulta, pois não contém todas as colunas. Sendo assim, ele
força o otimizador a ler o índice cluster também, para que assim possa reunir todos os
dados solicitados e devolver a consulta.
59
A Key Lookup ou Bookmark Lookup como era chamado no SQL SERVER 2000 é visto
em tabelas com índices clustered. Esse operador demonstra que o otimizador não consegue
recuperar as linhas com uma única operação e por isso necessita de uma clustered Key (ou
linha ID) para que assim retorne as linhas correspondentes usando um índice clustered (ou
da própria tabela). O operador Key Lookup é quando temos uma tabela com um índice
clustered, e o índice non clustered busca a chave da pesquisa no outro índice.
A Nested Loop join é uma operação padrão de associação, e não indica por si só
problema de desempenho. Para que esse tipo de operação seja requisitado é preciso
combinar as linhas do Index Seek e Key Lookup. Caso um índice de cobertura esteja
disponível, a Key lookup não será necessária e o operador Nested Loops não aparecerá no
plano de execução gráfico.
Se esse operador não for realmente necessário, sugere-se que ele seja retirado, para
que assim diminua a sobrecarga.
A table scan pode ocorrer por diversos motivos, porém geralmente é porque não
existem índices úteis na tabela, sendo assim necessário o otimizador de consulta pesquisar
todas as linhas em ordem para identificar as linhas que devem ser retornadas.
Outro motivo comum pelo qual ocorre uma table scan é quando todas as linhas de
uma tabela são retornadas. Quando a maioria das linhas trazidas pelo otimizador retorna
cada uma um índice.
Figura 7.28 – Exemplo de consulta que retorna os operadores merge join e hash
match
Merge Join: O otimizador de consulta também pode executar uma junção MERGE,
que correspondem a linhas de tabelas de entrada devidamente ordenadas explorando a sua
ordem de classificação.
65
Hash Match: Operações Hash são a segunda operação mais cara do plano de
execução. Hashing é uma técnica de programação onde os dados são convertidos em uma
forma simbólica que torna mais fácil e rápida a procura. Por outro lado, é uma estrutura de
dados que divide todos os elementos em categorias regularizadas, permitindo o acesso
rápido aos elementos. A junção Hash Match ocorre quando o SQL SERVER une duas
tabelas, juntando linhas da menor com a maior, verificando as linhas que precisam ser
unidas e inserindo-as em uma outra tabela hash. Portanto, se ambas as tabelas são muito
grandes, um junção Hash Match pode ser muito ineficiente em comparação com outros tipos
de associações.
66
8. ESTUDO DE CASO
8.1 O SGBD
O SGBD escolhido para realização deste estudo foi o SQL SERVER 2008.
8.1.2 Infraestrutura
• Hardware:
4 GB de memória RAM;
• Software:
Os testes foram realizados a partir de consultas que sofrem alterações de acordo com
a utilização de métodos de junção diferentes, utilização ou não de índices, chaves primárias
e chaves de junção.
67
Para realização deste estudo de caso foi utilizada a base de dados AdventureWorks,
base esta, própria da Microsoft, contendo o tamanho de 20.10 MB.
8.3 Testes
Resultados obtidos:
Plano de execução:
Resultados obtidos:
Plano de execução:
Observa-se nos casos acima, que não houve diferença relevante entre as duas
consultas. Portanto, nesses casos os comandos EXISTS e INNER JOIN possuem a mesma
funcionalidade.
a) SELECT Name,ProductSubcategoryID
FROM Production.Product
WHERE ProductSubcategoryID NOT IN ( SELECT ProductSubcategoryID FROM
Production.ProductSubcategory WHERE Name = 'Mountain Bikes' )
ORDER BY ProductSubcategoryID
70
Resultados Obtidos:
Plano de execução:
b) SELECT Name,ProductSubcategoryID
FROM Production.Product
WHERE ProductSubcategoryID IN ( SELECT ProductSubcategoryID FROM
Production.ProductSubcategory WHERE Name <> 'Mountain Bikes' )
ORDER BY ProductSubcategoryID
Resultados obtidos:
Plano de execução:
Nos testes acima, foi possível constatar que no item a, o qual se utilizou o comando
NOT IN, gerou um plano de execução com um número maior de operadores com relação ao
item b, apesar de fazer uso de índices para realização da consulta. Devido a isso, a consulta
possui um desempenho menor com relação ao item b, que possui um número menor de
operadores, sendo assim utilizando menos recursos do SQL SERVER.
Para realização deste teste, foi criado uma nova tabela na base de dados
AdventureWorks chamada de Curso.Pessoa. Abaixo seguem os passos:
Essa consulta demonstra informações dos tipos de índices existentes na tabela. Nesse
momento, o resultado trará apenas um índice clustered, que por padrão do SQL SERVER é
criado no momento que se define a primary key.
SET STATISTICS IO ON
SELECT p.Idade FROM Curso.Pessoa p
WHERE Codigo = 20000
73
Nessa consulta, observa-se que o SQL não utilizou o índice, fazendo apenas um index
scan, isto é, faz uma varredura em toda a tabela, pois a cláusula WHERE especifica como
parâmetro o atributo Nome, que não é uma chave para o índice clustered.
• Linhas afetadas: 1;
• Tempos de execução do SQL SERVER: CPU = 31 ms; tempo decorrido = 31 ms.
• Tempo de análise e compilação do SQL SERVER: CPU = 0 ms; tempo decorrido = 1
ms.
• TotalSubtreeCost: 0,7267
Cria-se então um índice nonclustered contendo como chave o atributo Nome, com o
comando abaixo:
• Linhas afetadas: 1;
• Tempos de execução do SQL SERVER: CPU = 0 ms; tempo decorrido = 2 ms.
• Tempo de análise e compilação do SQL SERVER: CPU = 0 ms; tempo decorrido = 0
ms.
• TotalSubtreeCost: 0,0065704
No teste abaixo, observa-se que o SQL fez uso apenas do índice nonclustered, pois
na SELECT foi solicitado os campos Codigo e Nome, campos estes existentes no índice
nonclustered.
Resultados Obtidos:
Diante dos testes realizados, foi possível notar casos onde o desempenho não fez
diferença, e também casos em que o desempenho teve uma melhora relevante. No Teste 1,
notou-se que operações com os comandos EXISTS e INNER JOIN produziram o mesmo
resultado final. Desta maneira, não existe diferença no custo total dessas operações,
podendo usar um ou outro que a perfomance será a mesma.
No Teste 3, que analisa o uso ou não de índices, demonstrado na tabela abaixo, foi
possível visualizar que quando o SQL faz o uso de índices, o desempenho torna-se melhor,
com um custo total menor. É importante também fazer uma análise das consultas que são
executadas com mais freqüência, para que desta maneira seja possível criar e projetar
76
índices apropriados, para que assim a performance seja a melhor possível através da
otimização. É importante ressaltar, que mesmo tendo índices disponíveis, às vezes o SQL
não os utiliza. Isso se deve porque o SQL deduz que é mais fácil realizar uma table scan,
devido ao fato da tabela ser pequena, tendo um custo menor do que ir até o índice, buscar a
chave e devolver a consulta através dele. Abaixo segue a tabela com o resultado do Teste
3:
Diante disso, os ajustes no banco de dados devem ser feitos de maneira adequada,
para que se possam perceber quaisquer modificações, evitando-se assim que ocorram
conseqüências que possam prejudicar a integridade do banco de dados.
Sendo assim, o estudo de caso pode ajudar e comprovar que pequenos ajustes
acarretam em grandes saltos no desempenho, porém deve-se ter cautela de modo a não
prejudicar outros aspectos do SGBD, por exemplo, fazendo uso de índices em demasia.
REFERÊNCIAS BIBLIOGRÁFICAS
_______. O que é melhor? Um Index Seek ou Clustered Index Scan?. Disponível em:
<http://fabianosqlserver.spaces.live.com/blog/cns!52EFF7477E74CAA6!693.entry>. Acesso
em: 21 ago. 2010.
CARNEIRO, Alessandro P.; MOREIRA, Julinao L.; FREITAS, Andre L.C. Tuning –
Técnicas de Otimização de Banco de Dados – Um Estudo Comparativo: Mysql e
Postgresql. Disponível em: <http://www.projetos.unijui.edu.br/erbd2009/arquivo/51990.pdf>.
Acesso em: 03 mar. 2010.
79
FRITCHEY, Grant. Dissecting SQL SERVER Execution Plans. Disponível em: <http://cid-
52eff7477e74caa6.skydrive.live.com/self.aspx/Publica/Art%20of%20High%20Performance%
20SQL%20Code%20by%20Grant%20Fritchey.pdf#resId/52EFF7477E74CAA6!781>.
Acesso em: 09 set. 2010.
MOREIRA, Luciano C. Porque o SQL SERVER não usa o meu índice?. Disponível em:
<http://blogs.msdn.com/b/luti/archive/2008/02/15/porque-o-sql-server-n-o-usa-o-meu-
ndice.aspx>. Acesso em: 18 ago. 2010.
VIEIRA, Eduardo B.; TAKANO, Leonardo M.; FORNACIARI, Lucas C. Metodologia para
Ajuste de Performance . Disponível em:
<http://www.shammas.eng.br/acad/sitesalunos0606/rpt/tun_met.html>. Acesso em: 01 jun.