Eu tenho uma tabela (com 170 milhões de linhas) com a seguinte aparência:
CREATE TABLE [dbo].[Panel]
(
[SubId] [varchar](15) NOT NULL,
[LineageId] [int] NULL,
[Buck] [varchar](20) NULL,
[Lot] [varchar](20) NULL,
[GlassType] [varchar](20) NULL,
[ETA] [varchar](200) NULL,
CONSTRAINT [PK_Panel] PRIMARY KEY CLUSTERED
(
[SubId] ASC
)
99% das consultas nessa tabela fazem referência a SubId na cláusula Where ou na junção. Um de nossos DBAs me disse que poderia melhorar o desempenho de todas essas consultas e junções criando o seguinte índice:
CREATE UNIQUE NONCLUSTERED INDEX [IX-Panel-SubID-I-LineageID] ON [dbo].[Panel]
(
[SubId] ASC
)
INCLUDE ([LineageId])
Quando ele me disse isso, pensei que ele estava louco. Mas acabei de verificar o uso do índice desde que esse índice foi criado e encontrei o seguinte:
PK_Panel (232,394 seeks / 2,133 scans)
IX-Panel-SubID-I-LineageID (25,528 seeks / 3644 scans)
Fiquei um pouco chocado ao ver isso. Em que circunstâncias esse novo índice seria usado? Por que o SQL Server o selecionaria?
Ou talvez uma pergunta melhor seria, por que o SQL Server selecionaria o novo índice para fazer uma busca, em vez do índice clusterizado? Aproximadamente 25 mil vezes, ele pensou que buscar no novo índice era uma escolha melhor.
Caso isso ajude, o LineageId indica essencialmente onde um painel foi criado e há cerca de 35 valores distintos que ele pode conter.
Criar um índice na coluna envolvida na chave de agrupamento pode parecer um pouco estranho. Alguém pergunta por que criar outro índice, quando já existe um?
O índice clusterizado é a tabela. Ou seja, seu índice clusterizado para esta tabela é semelhante a um índice como:
Claramente, isso não é o mesmo que um índice não clusterizado na chave de clustering, que no seu caso apenas "inclui" a
LineageId
coluna:Como teste, criei um modelo de sua tabela e inseri mais de 700.000 linhas nela:
Em seguida, executei a seguinte consulta para ver as estatísticas sobre os dois índices:
Os resultados da consulta acima são:
Claramente, o índice não clusterizado é menor que o índice clusterizado. Neste caso, cerca de 1/5 do tamanho. Ser um índice menor significa que o otimizador de consulta escolherá usá-lo quando o índice atender aos requisitos da consulta, de uma forma ou de outra.
Por exemplo,
só precisará ler 1.304 páginas do disco verificando o índice não clusterizado, em vez de ter que ler 7.105 páginas para verificar o índice clusterizado.
Por outro lado, para uma consulta que faz referência a colunas que não estão
included
no índice não clusterizado, o SQL Server provavelmente usará o índice clusterizado, pois ele atende aos requisitos da consulta.Tomemos, por exemplo, a consulta a seguir, onde você pode pensar intuitivamente que o otimizador de consulta pode escolher o índice não clusterizado, pois pode usá-lo para cumprir a
WHERE
cláusula, no entanto, o simples ato de procurar aBuck
coluna significa que é mais rápido simplesmente busque o índice clusterizado para os valores noWHERE
, então retorne as 3 colunas naSELECT
cláusula:Isso é um pouco simplificado, eu recomendo olhar para as páginas de índice de Brent Ozar
Escolher um índice mais restrito geralmente é melhor, especialmente se cobrir, o que significa que as consultas que usam buscas provavelmente só precisam de SubID e possivelmente LineageID. Embora, mesmo que o índice não cubra, ele ainda pode escolher o índice mais restrito e realizar pesquisas para a(s) coluna(s) adicional(is) se a contagem de linhas for pequena o suficiente para que isso ainda seja menos dispendioso no geral.
A menos que as consultas realmente exijam todas ou a maioria das colunas da tabela, o índice clusterizado seria uma escolha ruim, porque está espalhado por muito mais páginas, o que significa mais E/S para obter o subconjunto de colunas de que você precisa. Se tudo isso puder ser obtido do índice mais restrito, será a maneira mais barata de acessar os dados.
O custo é amplamente determinado pelo número de páginas que precisam ser lidas para satisfazer a consulta. O índice clusterizado é a tabela inteira, portanto, nunca será mais fino do que qualquer índice não clusterizado. Isso significa que, geralmente, para o mesmo número de linhas, o índice clusterizado exigirá mais E/S do que o índice não clusterizado. As escalas caem quando o índice não clusterizado não atende à consulta, o que significa que o SQL Server precisa escolher entre ir para o índice clusterizado e ir para o índice não clusterizado e realizar pesquisas. O último é julgado com base aproximadamente no número estimado de linhas e larguras de coluna, então realmente há muito "depende" que entrará em jogo.
Infelizmente, as estatísticas de uso do índice DMV não distinguem entre uma busca singleton e uma busca disfarçando uma varredura de intervalo (seja 2 linhas ou 2 milhões de linhas), portanto, apenas ver uma série de buscas versus varreduras não nos diz realmente o toda a história. E não temos informações suficientes sobre suas consultas reais para mostrar exatamente por que essa escolha foi feita, mas espero ter indicado o motivo provável pelo menos em alto nível.