Eu tenho tabelas Log e LogItem; Estou escrevendo uma consulta para pegar alguns dados de ambos. São milhares Logs
e cada um Log
pode ter até 125LogItems
A consulta em questão é complicada, então estou pulando (se alguém achar que é importante, provavelmente posso postá-la), mas quando executei o plano SSMS Estimated Query, ele me disse que um novo índice não clusterizado melhoraria o desempenho em até 100% .
Existing Index: Non-clustered
Key Colums (LogItem): ParentLogID, DateModified, Name, DatabaseModified
Query Plan Recommendation
CREATE NONCLUSTERED INDEX [LogReportIndex]
ON [dbo].[LogItem] ([ParentLogID],[DatabaseModified])
Apenas por diversão, criei este novo índice e executei a consulta e, para minha surpresa, agora leva cerca de 1 segundo para minha consulta ser executada, quando antes levava mais de 10 segundos.
Presumi que meu índice existente cobriria essa nova consulta, então minha pergunta é por que a criação de um novo índice nas únicas colunas usadas em minha nova consulta melhorou o desempenho? Devo ter um índice para cada combinação exclusiva de colunas usadas em minhas where
cláusulas?
nota: não acho que seja porque o SQL Server está armazenando em cache meus resultados, executei a consulta cerca de 25 a 30 vezes antes de criar o índice e demorou consistentemente de 10 a 15 segundos, após o índice agora é consistentemente ~ 1 ou menos.
A ordem das colunas em um índice é importante. Se a filtragem exigir as colunas 1 e 4 do índice, o índice não ajudará. Só é útil ao filtrar pelas primeiras N colunas consecutivas.
Isso ocorre porque index é uma árvore. Você não pode selecionar eficientemente todos os nós da árvore onde
column3 = something
, porque eles estão espalhados por todo o lugar, pertencentes a diferentes valores decolumn1
ecolumn2
. Mas se você soubercolumn1
ecolumn2
também, localizar o galho certo na árvore é óbvio.A vanguarda de um índice é o que importa.
Contanto que sua consulta seja "coberta" por uma ponta de um índice, ela será eficiente. Índices de banco de dados são normalmente implementados como B-Trees e a estrutura da B-Tree determina que a pesquisa deve ser feita em uma determinada ordem, e é por isso que a ordem dos campos no índice composto é importante.
Se você tiver "buracos", por exemplo, se pesquisar em
ParentLogID
eDatabaseModified
, mas tiver apenas um índice em{ParentLogID, DateModified, Name, DatabaseModified}
, somente a{ParentLogID}
parte do índice poderá ser utilizada com eficiência.(NOTA: Alguns DBMSes podem utilizar a
{DatabaseModified}
parte por meio de "pular varredura", mas mesmo que seu DBMS faça isso, é muito menos eficiente do que o acesso regular ao índice) .