bancos de dados sql server 2012 Índices. visão geral introdução arquitetura acesso aos dados...
TRANSCRIPT
Bancos de Dados
SQL Server 2012
Índices
Visão Geral
• Introdução • Arquitetura • Acesso aos dados armazenados• Manutenção das estruturas de Heap e Index• Quais colunas devem ser otimizadas?
Introdução
• Como o SQL Server armazena e acessa dados• Criar índices ou não?
Como o SQL armazena e acessa dados• Como os dados são armazenados?
– Linhas são armazenadas em páginas de dados– Heaps são coleções de páginas de dados de uma tabela
• Como os dados são acessados?– Lendo todas as páginas de dados em uma tabela (Table
Scanning)– Usando um índice que aponta para os dados da tabela
Como o SQL armazena os dados numa HEAP
• Cada página de dados contém 8KB de info.• Um grupo de 8 páginas adjacentes é denominado
extent• As linhas contendo dados não são armazenadas
em nenhuma ordem particular• As páginas de dados não são conectadas como em
uma lista encadeada• Quando linhas são inseridas em uma página e esta
fica cheia, o SQL quebra a página em duas (page split)
Como o SQL acessa os dados Escaneando todas as páginas da tabela – Table Scan– Começa na primeira página da tabela– Escaneia todas as páginas, lendo página por página– Extrai as linhas que atendem ao critério da consulta
Usando Índices– Atravessa a estrutura em árvore em busca das linhas
solicitadas pela consulta– Extrai somente as linhas que atendem ao critério da
consulta
Como o SQL acessa os dados • O SQL Server primeiro determina de um índice
existe. Então o query optimizer, responsável pela geração de um plano de execução otimizado para uma consulta, determina se é mais eficiente usar um índice ou escanear a tabela inteira
Devemos criar índices ou não?
• Porque criá-los?– Aumenta a velocidade de acesso aos dados– Garante a unicidade de linhas
• Porque não criá-los?– Consomem espaço em disco– Adicionam um overhead de atualização
Devemos criar índices ou não?
• Índices são criados e mantidos em ordem crescente ou decrescente
• Colunas com alto grau de seletividade, em que as colunas ou combinação de colunas possuem a maioria do dados sem repetições.
• Quando dados de uma coluna indexada são modificados, o SQL Server atualiza os índices automaticamente, o que aumenta o requerimentos de tempo e recursos.
Arquitetura
• Arquitetura de índices • Heaps• Índices do tipo Clustered• Índices do tipo Nonclustered
Arquitetura - Heaps
Usa páginas IAM (Index Allocation Map):• Contém informação de onde se encontram
armazenados os extents da heap que compõem a tabela
• Navega através da estrutura Heap a fim de encontrar espaço livre para inserção de novas linhas
• Conecta as páginas da tabela• Libera espaço para ser reusado em novas inserções
quando uma linha da tabela é deletada
Arquitetura – Índices Clustered
• Cada tabela pode ter somente um índice clustered
• A ordem física das linhas na tabela e a ordem das linhas no índice são as mesmas.
• Unicidade de chaves é mantida explicita (UNIQUE) ou implicitamente (identificador único interno adicionado à chave)
Arquitetura – Índices Nonclustered• Default to SQL Server• A ordem física das linhas na tabela e a ordem das linhas no
índice não são as mesmas• São reconstruídos sempre que:
– Índice clustered é criado ou deletado– A opção DROP_EXISITING é usada para modificar a ordem das
colunas• Mais eficientes em colunas variando de altíssima seletividade
a únicas• Crie sempre o índice clustered primeiro!• Consiste de valores de chave e identificadores de linha (File
ID, page number, row number)
Como o SQL Server acessa os dados
Assistir vídeo da MS sobre Index Architecture: http://www.youtube.com/watch?v=p9FlnOPltA8
• Buscando linhas sem uso de índices• Buscando linhas num HEAP via índice nonclustered• Buscando linhas num Índice Clustered• Buscando linhas num índice Clustered através de um
índice Nonclustered
Como o SQL Server acessa os dados
Buscando linhas sem uso de índices
Como o SQL Server acessa os dadosBuscando linhas num HEAP via índice Nonclustered
Como o SQL Server acessa os dadosBuscando linhas num HEAP via índice nonclustered:Exemplo:SELECT lastname, firstnameFROM memberWHERE lastnameBETWEEN 'Masters' AND 'Rudd '
Como o SQL Server acessa os dadosBuscando linhas num HEAP via índice Nonclustered
• Índices são B-Trees • Cada página de índice contém um cabeçalho seguido de linhas de índice• Cada linha de índice contém um valor de chave e um ponteiro para
outra página inferior na estrutura ou uma linha de dados• Cada página de um índice é chamada de nó• O nó superior é chamado de root node ou root level (raiz)• Os nós mais baixos são chamados de leaf node ou leaf level (nível folha)• Cada página nos níveis intermediários ou folha são ligados por uma lista
duplamente encadeada• Numa tabela que só contém índices nonclustered, os leaf nodes contém
localizadores de linha, que são ponteiros para as linhas de dados da tabela e são compostos pelo identificador do arquivo, número da página e número da linha dentro da página
Como o SQL Server acessa os dadosBuscando linhas num índice Clustered
Como o SQL Server acessa os dados Buscando linhas num índice Clustered
Exemplo:SELECT lastname, firstnameFROM memberWHERE lastname = 'Ota'
Como o SQL Server acessa os dados Buscando linhas num índice Clustered
• Também possui uma estrutura do tipo B-Tree• As páginas de dados de um índice clustered
são o nível folha da B-Tree• As linhas de dados de um índice clustered são
ordenados e armazenados em ordem sequencial baseada na chave do índice clustered
• Como num catálogo telefônico!• Só pode haver um índice clustered por tabela
Como o SQL Server acessa os dados Buscando linhas num índice Clustered
• A chave do índice clustered deve ser pequena, a fim de maximizar o número de linhas de índice por página, reduzindo a altura do índice e o número de I/Os.
• Se o índice clustered não for UNIQUE, o SQL Server adicionará ao final da chave um inteiro de 4-bytes, com valores supridos pelo sistema, a fim de distinguir valores duplicados.
Como o SQL Server Acessa os DadosBuscando linhas num índice Clustered através de um índice
Nonclustered
Como o SQL Server acessa os dados Buscando linhas num índice Clustered através
de um índice Nonclustered
Exemplo:SELECT lastname, firstname, phoneFROM memberWHERE firstname = 'Mike'
Como o SQL Server acessa os dados Buscando linhas num índice Clustered através de um
índice Nonclustered• Quando um índice nonclustered é adicionado a tabela e a
mesma já possui um índice clustered, o localizador de linha (row locator) do índice nonclustered passa ser a chave do índice clustered
• As estruturas B-Tree dos dois índices (nonclustered e clustered) devem ser atravessadas para acessar os dados, gerando mais I/O
• Já que a chave de um índice clustered é usualmente maior que os 8 bytes usados no ponteiro para HEAPs, os índices nonclustered podem ser substancialmente maiores quando forem montados sobre um índice clustered
• Mantenha a chave do índice clustered pequena, a fim de manter os índices nonclustered os menores possíveis.
Como o SQL Server mantém estruturas de Índice e Heap
• Page Splits em um índice• Forwarding Pointer num Heap• Como o SQL Server atualiza linhas• Como o SQL Server deleta linhas
Page Splits em um Índice
Page Splits em um Índice• Um índice clustered direciona uma linha a ser
inserida ou atualizada para uma página específica, que é determinada pelo valor da chave clustered.
• Se a página de dados ou índice não tiver espaço suficiente para acomodar os dados, uma nova página é adicionada, num processo denominado “page split”
• Aproximadamente metade dos dados permanece na página original, enquanto que a outra metade é movida para a nova página recém-criada
Page Splits em um Índice (cont.)• À nível lógico, a nova página é consecutiva à pagina
original. Fisicamente, porém a nova página poder ser alocada em qualquer lugar disponível
• Se num índice ocorre um número alto de page splits, deve-se fazer uma reconstrução (Rebuild) do mesmo
• Se ocorre um page split em um índice clustered, o SQL Server não necessita atualizar nenhum dos índices nonclustered para todas as linhas que forem movidas para a nova página. O localizador de linha continua a identificar a correta localização da chave clustered.
Forwarding Pointer num Heap
Forwarding Pointer num Heap• Page Splits não ocorrem em um Heap• Uma nova linha pode ser inserida em qualquer
lugar disponível• Se uma atualização em uma linha de um Heap
necessita de mais espaço do que o disponível na página, a linha é então movida para uma nova página de dados
• No lugar onde estava a linha antes da atualização, é colocado um Forwarding Pointer
Forwarding Pointer num Heap• Se a linha com o Forwarding Pointer precisar ser
movida novamente, o ponteiro original é modificado para apontar para a nova localização da linha
• O Forwarding Pointer faz com que os índices nonclustered não precisem ser mudados
• Se uma atualização faz com que a linha em questão encolha de tal maneira que a mesma caiba na sua localização original, o ponteiro é então eliminado e o linha recolocada em sua posição original
Forwarding Pointer num Heap
• Embora uma inserção ou atualização não possa causar um page split em um Heap, se um índice nonclustered existe com base em no mesma, então o split poderá ocorrer à nível do índice.
Como o SQL Server atualiza linhas
• Uma atualização geralmente não causa uma movimentação de linha, se após atualização a mesma puder ser acomodada na mesma página
Como o SQL Server atualiza linhas
• Updates em lote (batch) só tocam cada índice uma vez– Uma operação de pré-ordenamento (pre-sort) é
feita para que as atualizações ocorram na ordem do índice
– Aumento dramático em performance
Como o SQL Server atualiza linhas
• Uma atualização pode ocasionar uma deleção seguida de uma inserção– A atualização não cabe na mesma página– A tabela tem um trigger de update– A tabela é marcada para replicação– O valor da chave clustered requer que a linha seja
colocada em uma localização diferente. Ex: Se o sobrenome de uma pessoa mudar de Silva para Rocha terá que ser relocada numa lista telefônica
Como o SQL Server deleta linhas
Como o SQL Server deleta linhas
• Deleções causam registros fantasmas (Ghost Records)– Linhas deletadas do nível folha não são removidas
imediatamente– São marcadas inválidas e chamadas de Ghost
Records– Esse processo evita a necessidade de bloqueios por
faixa– Ghost Records são eliminados periodicamente pelo
SQL Server
Como o SQL Server deleta linhas
• Como o SQL Server realoca áreas deletadas– Quando a última linha de uma página é deletada, a página é
então desalocada, à menos que seja a última página da tabela
• Deletando linhas em um índice– Espaço fica disponível para uso imediatamente por linhas
adjacentes – Alguns gaps permanecem até que o índice seja reconstruído
• Deletando linhas em um Heap– Não são reusadas até que ocorram novas inserções
Enxugando arquivos de dados
• SQL Server move dados para páginas disponíveis no começo do arquivo
• Em índice páginas inteiras são movidas a fim de respeitar a ordenação
• Ponteiros de página são ajustados de acordo, a fim de manter a sequência
• Se não existe índice clustered, linhas individuais podem ser movidas para qualquer página
Quais colunas devem ser otimizadas?
• Entendendo os dados armazenados• Recomendações para indexação• Escolha do índice clustered apropriado• Indexação para suporte a consultas• Determinando a seletividade• Determinando a densidade• Determinando a distribuição de dados
Entendendo os dados armazenados
• Design Lógico e Físico• Características dos Dados• Como os dados são usados– Tipos de consultas executadas– Frequência em que as consultas são
executadasNão dá para tornar TODAS as consultas rápidas!
Recomendações para indexação
• Colunas que devem ser indexadas– Chaves primárias e chaves estrangeiras – As frequentemente usadas em consultas– As frequentemente acessadas em ordem numérica /
alfabética– As frequentemente agrupadas em agregações
• Colunas que não devem ser indexadas– As raramente referenciadas em consultas– As que contém poucos valores únicos– Colunas do tipo text, ntext, ou image
Escolha do índice clustered apropriado• Tabelas com alta frequência de modificações– Um índice clustered com identity mantem as
páginas alteradas em memória • Ordenação (Sorting)– O índice clustered mantém os dados preordenados
• Comprimento da coluna e tipo de dados– Limite o número de colunas– Reduza o número de caracteres (varchar X char)– Use o menor tipo de dados possível (tinyint X int)
Indexação para suporte a consultas• Search Arguments (SARGs)– Um SARG limita uma busca a valor exato, uma
faixa de valores ou uma combinação de dois ou mais itens conectados por um operador AND
– Um SARG contém uma expressão constante que age sobre uma coluna usando um operador
– Quando as consultas contém SARGs, aumentam-se as possibilidades do query optimizer usar um ou mais índices
Indexação para suporte a consultas• Escrevendo bons SARGs– Sempre especifique a cláusula Where –Certifique-se de que a cláusula Where limita
o número de linhas retornadas–Certifique-se de que existe uma expressão
para cada tabela referenciada na consulta– Evite usar coringas (wildcards) no inicio...
Indexação para suporte a consultas• Exemplos de bons SARGs
Where Cliente_Cod = 1234Where Cliente_Cod=1234 AND Cliente_Nome = ‘Paulo Chaves de Oliveira’Where Cliente_Cod in (1234, 6784, 2345)Where Cliente_Cod = 1234 AND Pedido_Cod = 8754Where Cliente_Nome like ‘Paulo%’Where Pedido_Cod between ‘02/17/2014 7:00’ AND ‘02/17/2014 20:00’
Indexação para suporte a consultas
• Exemplos de SARGs ruins e não-SARGS!Where Cliente_Cod <> 1234 – Pouco seletivo!Where Cliente_Cod=1234 OR Cliente_Sexo = ‘F’ – Mistura pouco com muito seletivo!Where Cliente_Cod NOT IN (1234, 6784, 2345) – Pouco seletivo! Where Cliente_Nome LIKE ‘%Paulo%’ – Wildcard no começo!Where Pedido_Cod between ’01/01/2001’ AND ‘02/17/2014’ -- Intervalo muito grande!Where datepart (yy, Pedido_Data) = 2001 – Lado esquerdo da expressão não é uma coluna, mas uma expressão! Obs: Poderia ser reescrito como Pedido_Data Between ‘01/01/2001’ AND ’12/31/2001 23:59.999’
Determinando a seletividade
Determinando a seletividade• Usada para descrever um predicado (predicate),
i.e., expressão que retorna verdadeiro ou falso• Seletividade é obtida do percentual de linhas em
uma tabela que são acessadas ou retornadas por uma consulta
• O query optimizer determina a seletividade para os comandos SELECT, UPDATE e DELETE
• Crie índices em: – Colunas que são frequentemente referenciadas em
operações de JOIN ou na cláusula WHERE– Colunas cujos dados são altamente seletivos
Determinando a seletividade
• Alta seletividade = Baixo percentual de retorno• Baixa seletividade = Alto percentual de retorno• Máxima seletividade = 1 linha retornada• Pode ser verificada por DBCC SHOWSTATISTICSEX: DBCC show_statistics (Cliente, Cliente_Estado)
Determinando a Densidade
Determinando a Densidade
• Usada para descrever os dados em uma coluna, ou seja, é uma medida de quão frequentemente valores duplicados ocorrem naquela coluna
• Mede o quão únicos são os dados em uma determinada coluna
• Quanto menor a densidade, mais únicos são os dados
Determinando a Densidade• A densidade (density) varia de 0 a 1• Density = 1/[Num. valores distintos na coluna] • Média do número de duplicatas para cada
valor de uma coluna• Qual é a densidade de uma Primary Key?
R: 1 / num. linhas• Qual é a densidade de uma coluna com um
valor repetido em todas as linhas?
Determinando a Densidade
Exercício:• Considere uma tabela Cliente com colunas
para Cod_Pais e Cod_Regiao (Estado)– 100 paises diferentes– 1000 regiões diferentes1. Calcular a densidade das duas colunas2. Rodar o script do próximo slide, para criar a
tabela Cliente. Verifique o conteúdo da mesma após a execução
Determinando a Densidadeuse tempdbgodrop table Clientegocreate table Cliente (Cod_Cliente int identity, Cod_Pais varchar(100), Cod_Regiao varchar(100))goset nocount onbegin trandeclare @x intset @x = 1while (@x <=10000)begin insert into Cliente (Cod_Pais, Cod_Regiao) values ('Cod_Pais' + convert (varchar, @x % 100), 'Cod_Regiao' + convert (varchar, @x % 1000)) set @x = @x + 1endwhile @@trancount > 0 commit trango
Determinando a Densidade
Exercício (cont.)3. Crie estatisticas para as colunas Cod_Pais e Cod_Regiao
create statistics stats_Cod_Pais on Cliente (Cod_Pais) with fullscancreate statistics stats_Cod_Regiao on Cliente (Cod_Regiao) with fullscanGo
4. Execute o dbcc show_statistics para as colunas Cod_Pais e Cod_Regiao
dbcc show_statistics (Cliente, stats_Cod_Pais)dbcc show_statistics (Cliente, stats_Cod_Regiao)go
Determinando a Densidade
5. Abra o link http://msdn.microsoft.com/pt-br/library/ms174384(v=sql.110).aspx e leia o conteúdo6. Analise os resultados das colunas
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
Determinando a distribuição de dados• SQL Server usa um histograma que mede a frequência
de ocorrência de cada valor distinto em um conjunto de dados
• O otimizador de consulta calcula um histograma – Selecionando os valores de coluna por amostragem
estatística OU– Executando uma verificação completa de todas as linhas da
tabela– Classificando os valores de colunas– Calcula o número de valores que correspondem a cada valor
distinto– Agregando os valores de colunas até um máx. de 200 etapas
Determinando a distribuição de dados
• Cada etapa inclui:– Uma gama de valores de colunas– Seguidos por um valor de limite superior– O intervalo inclui todos os possíveis valores de
coluna entre valores limite, excluindo-se os valores limite propriamente ditos
– O menor dos valores é o valor do limite superior da primeira etapa do histograma
Determinando a distribuição de dados• O diagrama a seguir mostra um histograma
com seis etapas:
Determinando a distribuição de dados• A linha em negrito é o valor do limite superior (RANGE_HI_KEY)
e o número de vezes que ele ocorre (EQ_ROWS) • A área sólida à esquerda de RANGE_HI_KEY é o intervalo de
valores de coluna e o número médio de vezes em que cada valor de coluna ocorre (AVG_RANGE_ROWS)
• As linhas pontilhadas são os valores amostrados usados para estimar o número total de valores distintos no intervalo (DISTINCT_RANGE_ROWS) e o número total de valores no intervalo (RANGE_ROWS)
• O otimizador de consulta usa RANGE_ROWS e DISTINCT_RANGE_ROWS para calcular AVG_RANGE_ROWS e não armazena os valores amostrados.
Exemplo de HIstogramaConsidere uma tabela de nome Pessoas, contendo uma coluna de nome Cod_Cidade. Um objeto de estatística foi criado para essa coluna, com o nome de ST_Pessoas_Cod_Cidade, através do comando:
CREATE STATISTICS ST_Pessoas_Cod_Cidade on Pessoas (Cod_Cidade) with fullscan.
A seguir executou-se o comando:DBCC SHOW_STATISTICS (Pessoas, ST_Pessoas_Cod_Cidade) with histogram
Exemplo de HistogramaRANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWSNULL 0 2938 0 1
0 0 2416 0 1382 5 16 5 1393 0 14 0 1451 0 1 0 1
... ... ... ... ...6881 0 18 0 16892 0 3 0 17165 0 116 0 17166 0 285 0 17738 6 5860 6 18062 0 1 0 18087 0 14 0 18340 0 3 0 1
... ... ... ... ...11074 0 5 0 111467 2 1 2 1
Exemplo de Histograma
• Determine a quantidade aproximada de linhas retornadas pelas consultas abaixo: – Select * from Pessoas where cod_cidade is NULL– Select * from Pessoas where cod_cidade = 451– Select * from Pessoas where cod_cidade > 11467– Select * from Pessoas where cod_cidade between
7166 and 7738– Select * from Pessoas where cod_cidade = 7375
Determinando a distribuição de dados
• Estimando o percentual de linhas retornadasSELECT column, count(*) AS 'Data Count'FROM tableGROUP BY columnORDER BY 'Data count' DESC
Exercício: Usar a consulta acima para Cod_Regiao e Cod_Pais na tabela Cliente
Exercício para Aula
1. Modificar a linha que insere dados na tabela de cliente para gerar códigos aleatórios de país e região :
insert into Cliente (Cod_Pais, Cod_Regiao) values ('Cod_Pais' + convert (varchar(20) , convert (int, floor ((rand () * 10000))) % 100), 'Cod_Regiao' + convert (varchar(20) , convert (int, floor ((rand () * 10000))) % 1000))
2. Executar o script modificado
Exercício para aula (cont.)
3. Imprimir os histogramas para as colunas supracitadas com a opção WITH HISTOGRAM do DBCC SHOW_STATISTICS4. Verificar valores de RANGE_HI_KEY, RANGE_ROWS, EQ_ROWS, DISTINCT_RANGE_ROWS e AVG_RANGE_ROWS para algumas etapas do histograma
Exercício para aula (cont.)
5. Ativar exibição do plano de execução no SQL Server Management Studio:
Menu Query / Include Actual Execution Plan OU ^M6. Verificar plano de execução de um full select:
Select * from Cliente7. Verificar plano de execução para uma região específica. Verificar que um table scan ocorreu:
Select * from Cliente Where Cod_Regiao = 'Cod_Regiao215'
Exercício para aula (cont.)
8. Determinar a distribuição dos dados para a coluna Cod_Regiao, anotando as regiões com menor e maior ocorrências:
Select Cod_Regiao, count(*) as Ocorrenciasfrom ClienteGroup by Cod_RegiaoOrder by Ocorrencias DESC
Exercício para aula (cont.)
9. Criar índice nonclustered em Cod_RegiaoCreate nonclustered index IX_Cliente_Cod_Regiao on Cliente (Cod_Regiao)go
10. Reexecutar a consulta do item 7 para as regiões de maior e menor ocorrências. Verificar se um índice foi utilizado. 11. Refazer os passos 7 a 10, agora para Cod_Pais e verificar se o índice adequado foi utilizado ou não, e determinar a razão.
Criando Índices
• Criando e excluindo índices• Criando índices UNIQUE• Criando índices compostos• Obtendo informações sobre índices• Opções para criação de índices
Criando e excluindo índices
• Usando o comando CREATE INDEXCREATE CLUSTERED INDEX CL_CLiente_Nome on dbo.Cliente (Cliente_Nome)
• Usando o comando DROP INDEXDROP INDEX dbo.Cliente.CL_CLiente_Nome
Criando e excluindo índicesSintaxe parcial do comando CREATE INDEX• CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ]• INDEX index_name ON { table | view } ( column [ ASC | DESC ]
[ ,...n ] )• [WITH• [PAD_INDEX ]• [[,] FILLFACTOR = fillfactor ]• [[,] IGNORE_DUP_KEY ]• [[,] DROP_EXISTING ]• [[,] STATISTICS_NORECOMPUTE ]• [[,] SORT_IN_TEMPDB ]• ]• [ON filegroup ]
Criando e excluindo índicesConsiderações sobre o comando CREATE INDEX– O SQL Server cria índices automaticamente quando uma
constraint do tipo UNIQUE ou PRIMARY KEY é criada na tabela– Criar uma CONSTRAINT que por sua vez cria um índice é
preferível a criar somente um índice UNIQUE.– Você deve ser o dono da tabela para criar um índice– Para visualizar informações sobre índices use sp_helpindex
(método antigo) ou as views sys.indexes e sys.index_columns (método moderno)
– Antes de criar um índice numa coluna determine se já existem índices na mesma
– Quando um índice clustered é criado, todos os índices nonclustered são recriados automaticamente.
Criando e excluindo índicesConsiderações sobre o comando DROP INDEX– O SQL Server libera o espaço em disco ocupado por
um índice quando o mesmo é excluído– Não se pode usar o comando DROP INDEX em
índices criados por constraints PRIMARY KEY ou UNIQUE. Deve-se excluir a constraint para que o respectivo índice seja excluído.
– Quando se exclui uma tabela, todos os respectivos índices são excluídos.
– Quando um índice clustered é excluído, todos os índices nonclustered são recriados automaticamente.
Criando índices UNIQUE
Exemplo:CREATE UNIQUE NONCLUSTERED INDEX UN_CLiente_CPF on dbo.Cliente (Cliente_CPF)
• É sempre preferível criar constraint UNIQUE!
Criando índices compostos
Criando índices compostos
Quando criá-los• Quando duas ou mais colunas são procuradas
como uma chave• Se as consultas referenciam somente as
colunas do índiceExemplo: Lista telefônica, índice composto em sobrenome e nome e possivelmente telefone
Criando índices compostosConsiderações• Pode-se combinar até 16 colunas num índice composto, desde
que a soma do comprimento das colunas não exceda 900 bytes• Todas as colunas de um índice composto devem ser da mesma
tabela• Se possível defina coluna com menos valores duplicados
primeiro. Esta coluna é chamada de coluna de ordem mais alta• A cláusula Where da consulta deve referenciar a primeira
coluna do índice composto para que o query optimizer considere o uso do índice
• Um índice em (coluna1, coluna2) não é o mesmo que um índice em (coluna2, coluna1), já que a ordem das colunas é diferente! Geralmente a coluna1 deveria ser mais seletiva que coluna2
Criando índices compostosConsiderações• Índices compostos são úteis para tabelas com
múltiplas colunas chave• Índices compostos podem aumentar o desempenho
e reduzir o número total de índices na tabela• Múltiplos índices compostos nas mesmas colunas
geralmente são pouco úteis.
Obtendo informações sobre índicesListando todos os índices de uma tabela (exemplo):
Use AdventureWorks2012SELECT i.name AS index_name ,i.type_desc ,is_unique ,ds.type_desc AS filegroup_or_partition_scheme ,ds.name AS filegroup_or_partition_scheme_name ,ignore_dup_key ,is_primary_key ,is_unique_constraint ,fill_factor ,is_padded ,is_disabled ,allow_row_locks ,allow_page_locksFROM sys.indexes AS iINNER JOIN sys.data_spaces AS ds ON i.data_space_id = ds.data_space_idWHERE is_hypothetical = 0 AND i.index_id <> 0 AND i.object_id = OBJECT_ID('Production.Product');GO
Obtendo informações sobre índicesListando todas as colunas que compõem um índice (exemplo):USE AdventureWorks2012;SELECT i.name AS index_name ,COL_NAME(ic.object_id,ic.column_id) AS column_name ,ic.index_column_id ,ic.key_ordinal,ic.is_included_columnFROM sys.indexes AS iINNER JOIN sys.index_columns AS ic ON i.object_id = ic.object_id AND i.index_id = ic.index_idWHERE i.object_id = OBJECT_ID('Production.BillOfMaterials');
Exercício para aulaUsando o script do exercício anterior, na versão randômica:1. Criar um índice em Cod_Pais e Cod_Regiao2. Criar um consulta que liste um Pais e Região
específicos. Verificar qual índice foi usado 3. Criar outro índice em Cod_Regiao e Cod_Pais4. Reexecutar a consulta do ítem2. Verificar qual índice foi
usado5. Listar todas as colunas que compõem os índices
existentes usando a consulta exemplo dos slides anteriores
6. Excluir o índice criado no item 1
Exercício para aulaUsando o script do exercício anterior, na versão randômica:7. Habilitar a exibição de estatísticas de IO
set statistics io ongo
8. Reexecutar a consulta do ítem 2. Verificar qual índice foi usado e quanto IOs lógicos foram necessários
9. Excluir o índice criado no item 310. Reexecutar a consulta do ítem2. Verificar qual índice
foi usado e quanto IOs lógicos foram necessários
Exercício para aulaUsando o script do exercício anterior, na versão randômica:11. Excluir o índice por Cod_Regiao12. Reexecutar a consulta do ítem2. Verificar qual
índice foi usado e quanto IOs lógicos foram necessários
Opções para criação de índices
• Fillfactor– Especifica o quanto as páginas devem ser cheias– Afeta apenas o nível folha
• PadIndex– Aplica o fillfactor aos níveis não-folha– Se não especificado, deixa uma entrada livre por
página no nível não-folha– Número de linhas no nível não-folha nunca é
menor que duas.
Opções para criação de índices
Opções para criação de índices• Considerações sobre o Fillfactor– Pode otimizar INSERTS e UPDATES– Minimiza o Page Split– Aplicado somente na criação ou reconstrução– Baixo em OLTP (online transactional processing)– Alto em OLAP (online analytical processing)– Varia de 0 a 100 (por cento)– Default é 0 (leaf level cheio e nonleaf level com
uma entrada livre)– Valores usuais entre 70 e 90 %
Opções para criação de índices
Exemplo de Fillfactor:
CREATE UNIQUE NONCLUSTERED INDEX CL_CLiente_CPF on dbo.Cliente (Cliente_CPF) WITH PAD_INDEX, FILLFACTOR=70
Exercício para aula
1. Criar índices apropriados no banco de dados do trabalho 1. Usar fillfactor = 70, sem padindex.
OBS: Se possível criar indices compostos2. Criar consultas que utilizem os índices
criados. Verificar que os mesmos estão sendo utilizados, solicitando a exibição do plano de execução
Manutenção de Índices
• Fragmentação de dados• Comando DBCC SHOWCONTIG• Comando DBCC INDEXDEFRAG• Opção DROP_EXISTING
Fragmentação de dados
• Como ocorre a fragmentação de dados– O SQL Server reorganiza as páginas de índice quando
os dados são modificados– O que inevitavelmente causa page splits
• Métodos para gerenciamento da fragmentação– Excluir e recriar um índice especificando um fillfactor– Reconstruir um índice especificando um fillfactor
• Ambiente comercial de negócios – Fragmentação de dados pode ser boa para OLTP– Fragmentação de dados pode ser ruim para OLAP
Comando DBCC SHOWCONTIG
Exibe informações de fragmentação para os dados e índices da tabela ou view especificada
O que o DBCC SHOWCONTIG determina– Se uma tabela ou índice está altamente
fragmentada – Se páginas de dados ou índice estão cheias
Comando DBCC SHOWCONTIG• Pages scanned: Número de páginas na tabela ou no índice.• Extents scanned: Número de extents na tabela ou no índice.• Extent switches: O número de vezes que a instrução DBCC foi
movida de uma extensão para outra enquanto atravessava as páginas da tabela ou do índice.
• Average pages per extent Número de páginas por extensão na cadeia de páginas.
• Scan density [Best Count: Actual Count] : É uma porcentagem. É a relação entre a Melhor Contagem e a Contagem Real. Esse valor será 100 se tudo for contíguo; se ele for menor que 100, isso indicará que existe alguma fragmentação. A Melhor Contagem será o número ideal de mudanças de extents se tudo for vinculado contiguamente. A Contagem Real é o número real de alterações de extensão.
Comando DBCC SHOWCONTIG• Logical scan fragmentation : Percentagem de páginas fora de
ordem retornadas da verificação de páginas de folha de um índice. Esse número não é relevante para heaps. Uma página fora de ordem é aquela para a qual a próxima página física alocada ao índice não é a página apontada pelo ponteiro da próxima página da página de nível folha atual.
• Extent scan fragmentation: Porcentagem de extents fora de ordem na verificação de páginas do nível folha de um índice. Esse número não é relevante para heaps. Uma extensão fora de ordem é aquela para a qual o extent que contém a página atual de um índice não é fisicamente o próximo extent depois do extent que contém a página anterior de um índice.
Comando DBCC SHOWCONTIG• Average bytes free per page: Número médio de bytes livres
em páginas verificadas. Quanto maior o número, mais vazias ficarão as páginas. Números inferiores serão melhores se o índice não tiver muitas inserções aleatórias. Esse número também é afetado pelo tamanho da linha; uma linha grande pode gerar um número maior.
• Average page density (full): Densidade média da página, expresso como uma porcentagem. Esse valor leva em consideração o tamanho de linha. Por isso, o valor é uma indicação mais precisa de quão cheias estão as páginas. Quanto maior a porcentagem, melhor.
Comando DBCC SHOWCONTIGUSE NorthwindDBCC SHOWCONTIG (Customers, PK_Customers)
DBCC SHOWCONTIG scanning 'Customers' table...Table: 'Customers' (2073058421); index ID: 1, database ID: 6TABLE level scan performed.Pages Scanned: 3Extents Scanned: 2Extent Switches: 1Avg. Pages per Extent: 1.5Scan Density [Best Count:Actual Count]: 50.00% [1:2]Logical Scan Fragmentation 0.00%Extent Scan Fragmentation: 50.00%Avg. Bytes Free per Page: 246.7Avg. Page Density (full): 96.95%DBCC execution completed. If DBCC printed error messages,contact your system administrator.
Exercício para sala
1. Modifique o script que cria a tabela Cliente em tempdb, na versão randômica, para adicionar uma Primary Key CLUSTERED em Cod_ClienteALTER TABLE Cliente ADD CONSTRAINT PK_Cliente PRIMARY KEY (Cod_Cliente)
2. Execute DBCC SHOWCONTIG para PK_Cliente3. Execute DBCC SHOWCONTIG para os demais índices
nonclustered (Cod_Pais e Cod_Regiao)4. Verificar qual deles possui a maior fragmentação
lógica
Comando DBCC INDEXDEFRAG• Desfragmenta o nível folha de um índice de
forma que a ordem física das páginas corresponda à ordem lógica da esquerda para a direita dos nós folha, melhorando assim o desempenho de consultas que usam o índice
• Operação online• Eficiente se a fragmentação for baixa• Pode gerar muito log• Compacta páginas e tenta manter o fillfactor• Não bloqueia recursos
Comando DBCC INDEXDEFRAGExemplo:DBCC INDEXDEFRAG (AdventureWorks2012, "Production.Product", PK_Product_ProductID)GOPages Scanned Pages Moved Pages Removed-------------------- -------------------- --------------------13 0 0
(1 row(s) affected)
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Exercício para sala
1. Desfragmentar com DBCC INDEXDEFRAG o índice nonclustered em Cod_Regiao na tabela Clientes do exercício anterior
2. Reexecutar DBCC SHOWCONTIG e verificar se a fragmentação lógica diminuiu
Opção DROP_EXISTING
• Reconstrói o índice– Reorganiza o nível folha– Remove a fragmentação– Recalcula as estatísticas
• Pode mudar as características de um índice– Tipo (nonclustered para clustered)– Colunas que compõem o índice– Opções (fillfactor, padindex)
Opção DROP_EXISTING
Exemplo:USE NorthwindCREATE INDEX OrderID_indON Orders(OrderID)WITH PAD_INDEX, FILLFACTOR=70, DROP_EXISTING
Exercício para Sala
1. Reconstruir com a opção DROP_EXISTING o índice nonclustered em Cod_Pais na tabela Clientes do exercício anterior
2. Reexecutar DBCC SHOWCONTIG e verificar se a fragmentação lógica diminuiu
Links Úteis• CREATE INDEX:
http://technet.microsoft.com/en-us/library/ms188783.aspx
• Vídeos sobre SQL Server Index Architecture:http://www.youtube.com/watch?v=p9FlnOPltA8 http://www.youtube.com/watch?v=xMOdcmNWdFs
Links Úteis• Query Tuning Fundamentals: Density, Predicates, Selectivity, and
Cardinalityhttp://blogs.msdn.com/b/bartd/archive/2011/01/25/query_5f00_tuning_5f00_key_5f00_terms.aspx
Statistics Used by the Query Optimizer in Microsoft SQL Server 2008http://msdn.microsoft.com/en-us/library/dd535534(v=sql.100).aspx
Sys.indexes e sys.index_columns system viewshttp://technet.microsoft.com/pt-br/library/ms173760.aspxhttp://technet.microsoft.com/pt-br/library/ms175105.aspx
Links Úteis• DBCC INDEXDEFRAGhttp://technet.microsoft.com/pt-br/library/ms177571.aspx
• DBCC SHOWCONTIGhttp://technet.microsoft.com/pt-br/library/ms175008.aspx