AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 112876
Accepted
Ian Boyd
Ian Boyd
Asked: 2015-09-02 11:14:35 +0800 CST2015-09-02 11:14:35 +0800 CST 2015-09-02 11:14:35 +0800 CST

Devo marcar um índice composto como único se ele contiver a chave primária?

  • 772

Dada alguma 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 única em CustomerID.

Tradicionalmente, posso precisar de alguns índices de cobertura adicionais; por exemplo, para encontrar rapidamente um usuário usando CustomerIDou Email:

CREATE INDEX IX_Customers_CustomerIDEmail ON Customers
(
   CustomerID,
   Email
)

E esses são os tipos de índices que criei por 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 auxiliar no desempenho (o índice não existe como uma restrição para impor exclusividade).

Hoje lembrei-me de uma pequena informação - o SQL Server pode usar o fato de que:

  • uma coluna tem uma restrição de chave estrangeira
  • uma coluna tem um índice único
  • uma restrição é confiável

para ajudá-lo a otimizar sua execução de consulta. Na verdade, do Guia de design do índice do SQL Server :

Se os dados forem exclusivos e você desejar a exclusividade aplicada, 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 . A criação de um índice exclusivo (de preferência criando uma restrição UNIQUE) é recomendada nesse caso.

Dado que meu índice de várias colunas contém a chave primária, esse índice composto será de fato exclusivo. Não é uma restrição que eu particularmente precise que o SQL Server aplique durante cada inserção ou atualização; mas o fato é que esse índice não agrupado é exclusivo.

Existe alguma vantagem em marcar esse índice único de fato como realmente único?

CREATE UNIQUE INDEX IX_Customers_CustomerIDEmail ON Clientes
(
   Identificação do Cliente,
   E-mail
)

Parece-me que o SQL Server pode ser inteligente o suficiente para perceber que meu índice já é exclusivo pelo 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 deve executar verificações de exclusividade - onde antes nunca precisava antes.
  • A menos que saiba que o índice já é exclusivo , porque 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 dos í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 único se ele já contiver a chave primária? Ou o SQL Server pode descobrir isso sozinho?

sql-server index
  • 2 2 respostas
  • 2726 Views

2 respostas

  • Voted
  1. Best Answer
    Paul White
    2015-09-02T20:08:51+08:002015-09-02T20:08:51+08:00

    Devo marcar um índice composto como único se ele já contiver a chave primária?

    Provavelmente não. O otimizador geralmente pode usar informações sobre a exclusividade da coluna de chave contida de qualquer maneira, portanto, não há nenhuma vantagem real.

    Há também uma consequência importante de marcar um índice exclusivo em planos de atualização que modificam as chaves desse índice a serem consideradas:

    Configurar

    CREATE TABLE dbo.Customers 
    (
       CustomerID int NOT NULL PRIMARY KEY,
       FirstName nvarchar(50),
       LastName nvarchar(50),
       [Address] nvarchar(200),
       Email nvarchar(260)
    );
    
    CREATE NONCLUSTERED INDEX 
        IX_Customers_CustomerIDEmail 
    ON dbo.Customers
    (
       CustomerID,
       Email
    );
    
    -- Pretend we have some rows
    UPDATE STATISTICS dbo.Customers 
    WITH ROWCOUNT = 100000, PAGECOUNT = 20000;
    

    Plano de atualização por índice (índice não exclusivo)

    UPDATE dbo.Customers 
    SET Email = N'New', [Address] = 'New Address'
    WHERE Email = N'Old' 
    OPTION (QUERYTRACEON 8790); -- Per-index update plan
    

    Plano de execução:

    Dividir e Filtrar

    O otimizador geralmente toma uma decisão baseada em custo entre atualizar índices não clusterizados por linha (um plano 'estreito') ou por índice (um plano 'amplo'). A estratégia padrão (exceto para tabelas OLTP na memória) é um plano amplo.

    Planos estreitos (onde os índices não clusterizados são mantidos ao mesmo tempo que o heap/índice clusterizado) são uma otimização de desempenho para pequenas atualizações. Essa otimização não é implementada para todos os casos - usar certos recursos (como exibições indexadas) significa que o(s) índice(s) associado(s) será(ão) mantido(s) 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 os índices clusterizados e não clusterizados sendo mantidos separadamente.

    O Split transforma cada atualização em um par delete & insert separado; 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)

    -- Same index, but unique
    CREATE UNIQUE INDEX IX_Customers_CustomerIDEmail ON Customers
    (
       CustomerID,
       Email
    )
    WITH (DROP_EXISTING = ON);
    
    UPDATE dbo.Customers 
    SET Email = N'New', [Address] = 'New Address'
    WHERE Email = N'Old' 
    OPTION (QUERYTRACEON 8790); -- Per-index update plan
    

    Plano de execução:

    Dividir-Ordenar-Recolher

    Observe os operadores adicionais Sort e Collapse quando o índice é marcado como exclusivo.

    Esse padrão Split-Sort-Collapse é 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

    O Sort em particular pode ser um problema. Além de ser um custo extra desnecessário, ele pode vazar para o disco se as estimativas forem imprecisas.

    Sobre chaves não clusterizadas

    Outro fator a ser considerado é que as estruturas de índice não clusterizadas são sempre exclusivas, em todos os níveis do índice, mesmo que UNIQUEnão sejam especificadas. A(s) chave(s) de clustering - e possivelmente um unificador se o índice clusterizado não estiver marcado como exclusivo - são adicionados a um índice não clusterizado não exclusivo em todos os níveis.

    Como consequência, a seguinte definição do índice:

    CREATE INDEX IX_Customers_CustomerIDEmail ON Customers
    (
       Email
    )
    WITH (DROP_EXISTING = ON);
    

    ...na verdade contém as chaves (Email, CustomerID) em todos os níveis. É, portanto, 'buscável' em ambas as colunas:

    SELECT * 
    FROM dbo.Customers AS C WITH (INDEX(IX_Customers_CustomerIDEmail))
    WHERE C.Email = N'Email'
    AND C.CustomerID = 1;
    

    procura

    Mais informações: Mais sobre chaves de índice não clusterizadas por Kalen Delaney

    • 12
  2. Rob Farley
    2015-09-02T13:13:31+08:002015-09-02T13:13:31+08:00

    O SQL já sabe que é exclusivo (se incluir o PK, não pode ser mais exclusivo), independentemente de você dizer isso explicitamente.

    A grande diferença entre um índice não exclusivo e um índice exclusivo é que os índices não exclusivos exigem a chave de índice clusterizado (com valor unificador 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 tenha um PK (único) e um CIX separados (não importa). Em seguida, crie um índice não exclusivo que inclua o 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 DBCC IND para localizar as páginas em seu NCIX e DBCC PAGE para abrir algumas para examinar os dados, para ver se os valores da chave CIX estão nos níveis mais altos.

    • 8

relate perguntas

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Quanto "Padding" coloco em meus índices?

  • Como determinar se um Índice é necessário ou necessário

  • O que significa "índice" em RDBMSs? [fechado]

  • Como criar um índice condicional no MySQL?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve