Declarando um índice como único em SQL Server
-
09-09-2019 - |
Pergunta
Se eu sei que um índice terão valores exclusivos, como é que vai afetar o desempenho em inserções ou seleciona se eu declará-la como tal.
Se o otimizador sabe o índice é único como isso vai afetar o plano de consulta?
Eu entendo que especificar uniquenes pode servir para preservar a integridade, mas deixando que a discussão de lado para o momento, quais são as consequências perfomance.
Solução
Para encurtar a história:. Se seus dados são intrinsecamente UNIQUE
, você será beneficiado com a criação de um índice UNIQIE
sobre eles
Veja o artigo em meu blog para explicação detalhada:
Agora, os detalhes.
As @Mehrdad disse, UNIQUENESS
afeta a contagem de linhas estimado no construtor de plano.
índice UNIQUE
tem máxima seletividade possível, é por isso:
SELECT *
FROM table1 t2, table2 t2
WHERE t1.id = :myid
AND t2.unique_indexed_field = t1.value
quase certamente irá usar NESTED LOOPS
, enquanto
SELECT *
FROM table1 t2, table2 t2
WHERE t1.id = :myid
AND t2.non_unique_indexed_field = t1.value
pode beneficiar de uma HASH JOIN
se o otimizador pensa que non_unique_indexed_field
não é selectiva.
Se o seu índice é CLUSTERED
(ou seja, as linhas theirselves estão contidos nas folhas de índice) e não-UNIQUE
, em seguida, uma coluna especial escondido chamado uniquifier
é adicionado a cada chave de índice, tornando assim a chave maior e o índice mais lento.
É por isso índice UNIQUE CLUSTERED
é na verdade um pouco mais efficicent do que um non-UNIQUE CLUSTERED
.
Em Oracle
, uma junção em UNIQUE INDEX
é necessário para tal chamado key preservation
, o que garante que cada linha de uma tabela serão selecionados, no máximo, uma vez e faz um atualizável exibição.
Esta consulta:
UPDATE (
SELECT *
FROM mytable t1, mytable t2
WHERE t2.reference = t1.unique_indexed_field
)
SET value = other_value
trabalhará em Oracle
, enquanto este:
UPDATE (
SELECT *
FROM mytable t1, mytable t2
WHERE t2.reference = t1.non_unique_indexed_field
)
SET value = other_value
falhará.
Este não é um problema com SQL Server
, no entanto.
Mais uma coisa: para uma tabela como esta,
CREATE TABLE t_indexer (id INT NOT NULL PRIMARY KEY, uval INT NOT NULL, ival INT NOT NULL)
CREATE UNIQUE INDEX ux_indexer_ux ON t_indexer (uval)
CREATE INDEX ix_indexer_ux ON t_indexer (ival)
, esta consulta:
/* Sorts on the non-unique index first */
SELECT TOP 1 *
FROM t_indexer
ORDER BY
ival, uval
usará um TOP N SORT
, enquanto este:
/* Sorts on the unique index first */
SELECT TOP 1 *
FROM t_indexer
ORDER BY
uval, ival
usará apenas uma verificação do índice.
Para a última consulta, não há nenhum ponto na classificação adicional sobre ival
, desde uval
são de qualquer maneira única, e o otimizador leva isso em conta.
Em dados de amostra de linhas 200,000
(id == uval == ival
), o ex-consulta é executada para segundos 15
, enquanto o último é instantânea.
Outras dicas
Claro que o otimizador terá exclusividade em consideração. Ela afeta a contagem de linhas esperado em planos de consulta.
O desempenho é afetado negativamente quando inserir dados. Ele precisa verificar a unicidade.
Eu apenas testei isso na minha máquina para uma mesa de Produção contendo mais de 1 milhão de linhas, porque achei que era um bom teste. Os resultados foram interessantes, aqui está os números brutos:
- No índice:
Setup Time: 8888, Insert Time: 501690
- Única restrição:
Setup Time: 42, Insert Time: 488030
A configuração consistia em obter o máximo do campo que eu estava adicionando a restrição exclusiva para - assim logicamente o desempenho foi aumentado dramaticamente adicionando a restrição. Isso também melhorar o desempenho na busca por esta chave estrangeira.
Curiosamente o tempo de inserção melhorou ligeiramente, bem como (por 2,7228%), portanto, apenas impactos positivos [no meu caso de teste] de adicionar a restrição (+ índice inerente).
Teste mostra apenas impactos positivos de adicionar a restrição -. Nenhum impacto no desempenho
NOTA:. Para o nosso sistema de teste Espero que os valores para quase sempre ser único, então eu não testar a inserção de valores não-exclusivos, nestes dados é realmente uma exceção - e não algo que precisa ser alto desempenho
Sim, ele vai ser levado em consideração pelo mecanismo de consulta.
Talvez mais importante: a singularidade irá proteger a integridade dos dados. Desempenho seria uma razão para ignorar isso.
Desempenho pode ser afetado positiva ou negativamente ou não em todos: seria depende da consulta, se o índice é usado etc