Dada uma tabela com uma chave primária, por exemplo:
CREATE TABLE Customers (
CustomerID int NOT NULL PRIMARY KEY,
FirstName nvarchar(50),
LastName nvarchar(50),
Address nvarchar(200),
Email nvarchar(260)
--...
)
temos uma chave primária exclusiva ativada CustomerID
.
Tradicionalmente, talvez eu precise de alguns índices de cobertura adicionais; por exemplo, para encontrar rapidamente um usuário com um CustomerID
ou Email
:
CREATE INDEX IX_Customers_CustomerIDEmail ON Customers
(
CustomerID,
Email
)
E esses são os tipos de índices que eu criei há décadas.
Não é necessário ser único, mas na verdade é
O próprio índice existe para evitar uma varredura de tabela; é um índice de cobertura para ajudar no desempenho (o índice não existe como uma restrição para impor exclusividade).
Hoje, lembrei-me de um pouco de informações - o SQL Server pode usar o fato de que:
- uma coluna tem uma restrição de chave estrangeira
- uma coluna possui um índice exclusivo
- uma restrição é confiável
para ajudá-lo a otimizar a execução da consulta. De fato, no Guia de Design de Índice do SQL Server :
Se os dados forem exclusivos e você desejar aplicar a exclusividade, a criação de um índice exclusivo em vez de um índice não exclusivo na mesma combinação de colunas fornece informações adicionais para o otimizador de consulta que pode produzir planos de execução mais eficientes . É recomendável criar um índice exclusivo (de preferência criando uma restrição UNIQUE) neste caso.
Dado que meu índice de várias colunas contém a chave primária, esse índice composto será de fato único. Não é uma restrição que eu particularmente precise do SQL Server para impor durante cada inserção ou atualização; mas o fato é que esse índice não clusterizado é único.
Existe alguma vantagem em marcar esse índice exclusivo de fato como realmente único?
CRIAR ÍNDICE UNIQUE IX_Customers_CustomerIDEmail ON Customers ( Identificação do Cliente, O email )
Parece-me que o SQL Server pode ser inteligente o suficiente para perceber que meu índice já é exclusivo em virtude do fato de conter a chave primária.
- Mas talvez ele não saiba disso, e há uma vantagem para o otimizador se eu declarar o índice como único de qualquer maneira.
- Exceto, talvez, que agora possa levar a lentidão durante inserções e atualizações, onde é necessário executar verificações de exclusividade - onde antes nunca era necessário.
- A menos que saiba que o índice já é garantido , ele contém a chave primária.
Não consigo encontrar nenhuma orientação da Microsoft sobre o que fazer quando um índice composto contém a chave primária.
Os benefícios de índices exclusivos incluem o seguinte:
- A integridade dos dados das colunas definidas é garantida.
- Informações adicionais úteis para o otimizador de consulta são fornecidas.
Devo marcar um índice composto como exclusivo se ele já contiver a chave primária? Ou o SQL Server pode descobrir isso por si mesmo?
fonte
Respostas:
Provavelmente não. O otimizador geralmente pode usar informações sobre a exclusividade da coluna de chave contida, de modo que não há vantagem real.
Há também uma consequência importante de marcar um índice exclusivo nos planos de atualização que modificam as chaves desse índice a serem consideradas:
Configuração
Plano de atualização por índice (índice não exclusivo)
Plano de execução:
O otimizador geralmente toma uma decisão baseada em custo entre atualizar índices não clusterizados por linha (um plano 'restrito') ou por índice (um plano 'amplo'). A estratégia padrão (exceto tabelas OLTP na memória) é um plano amplo.
Planos restritos (em que índices não clusterizados são mantidos ao mesmo tempo que o índice de heap / cluster) são uma otimização de desempenho para pequenas atualizações. Essa otimização não é implementada para todos os casos - o uso de certos recursos (como visualizações indexadas) significa que os índices associados serão mantidos em um plano amplo.
Mais informações: Otimizando consultas T-SQL que alteram dados
Nesse caso, usei o sinalizador de rastreamento não documentado 8790 para forçar um amplo plano de atualização: O plano, portanto, mostra que os índices clusterizados e não clusterizados são mantidos separadamente.
O Split transforma cada atualização em um par separado de excluir e inserir; o filtro filtra todas as linhas que não resultariam em uma alteração no índice.
Mais informações: ( atualizações sem atualização ) pela equipe de QO do SQL Server.
Plano de atualização por índice (índice exclusivo)
Plano de execução:
Observe os operadores extras de classificação e recolhimento quando o índice estiver marcado como exclusivo.
Esse padrão de divisão, classificação e recolhimento é necessário ao atualizar as chaves de um índice exclusivo, para evitar violações intermediárias de chaves exclusivas.
Mais informações: Manutenção de índices exclusivos por Craig Freedman
A classificação em particular pode ser um problema. Além de ser um custo extra desnecessário, ele pode se espalhar para o disco se as estimativas forem imprecisas.
Sobre chaves não clusterizadas
Outro fator a considerar é que as estruturas de índice não clusterizadas são sempre únicas, em todos os níveis do índice, mesmo que
UNIQUE
não sejam especificadas. A (s) chave (s) de cluster - e possivelmente um uniquificador se o índice em cluster não estiver marcado como exclusivo - são adicionadas a um índice não clusterizado não exclusivo em todos os níveis.Como conseqüência, o seguinte índice foi definido:
... na verdade contém as chaves (Email, CustomerID) em todos os níveis. Portanto, é 'procurável' nas duas colunas:
Mais informações: Mais sobre chaves de índice não clusterizadas por Kalen Delaney
fonte
O SQL já sabe que é exclusivo (se incluir o PK, ele não poderá ser mais exclusivo), independentemente de você explicitamente informar.
A grande diferença entre um índice não exclusivo e um índice exclusivo é que os índices não exclusivos requerem a chave de índice em cluster (com valor uniquificador se o CIX não for declarado como exclusivo) nos níveis mais altos do índice, não apenas na folha nível.
No seu caso, você já tem o CIX na chave, o que significa que já estará em todos os níveis do índice.
Mas você pode criar uma tabela que possui um PK (exclusivo) e um CIX (não importa). Em seguida, crie um índice não exclusivo que inclua a PK em sua chave. Coloque algumas linhas na tabela, incluindo alguns valores varchar facilmente localizáveis para sua coluna CIX. Coloque linhas suficientes para causar vários níveis de seus índices. Em seguida, você pode usar o DBCC IND para localizar as páginas em seu NCIX e o DBCC PAGE para abrir alguns para examinar os dados e verificar se os valores da chave CIX estão nos níveis mais altos.
fonte