Eu tenho tabelas Log e LogItem; Estou escrevendo uma consulta para pegar alguns dados de ambos. Existem milhares Logs
e cada um Log
pode ter até 125LogItems
A consulta em questão é complicada, por isso estou ignorando (se alguém acha importante, provavelmente posso publicá-la), mas quando executei o plano de Consulta Estimada do SSMS, 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 esse novo índice e executei a consulta e, para minha surpresa, agora leva cerca de 1 segundo para que minha consulta seja executada, antes de mais de 10 segundos.
Eu supus que meu índice existente cobriria essa nova consulta; portanto, minha pergunta é por que a criação de um novo índice nas únicas colunas usadas na minha nova consulta melhorou o desempenho? Devo ter um índice para cada combinação exclusiva de colunas usada em minhas where
cláusulas?
nota: acho que isso não ocorre porque o SQL Server está armazenando meus resultados em cache, executei a consulta cerca de 25 a 30 vezes antes de criar o índice e demorou 10 a 15 segundos, depois que o índice agora está consistentemente ~ 1 ou menos.
fonte
Respostas:
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 N primeiras colunas consecutivas.
Isso ocorre porque o índice é uma árvore. Você não pode selecionar com eficiência todos os nós da árvore onde
column3 = something
, porque eles estão espalhados por todo o outro lugar, pertencendo a diferentes valores decolumn1
ecolumn2
. Mas se você soubercolumn1
ecolumn2
também, localizar o galho certo na árvore é um acéfalo.fonte
where
s podem se sobrepor, então você pode ter um índice que cubra muito bem várioswhere
s; ou você pode ignorar parte de umawhere
cláusula porque a indexação em uma determinada coluna não ajuda em nada (baixa seletividade); mas amplamente, sim.where
cláusulas não é importante. O servidor sempre as organizará para fazer o melhor uso dos índices existentes. É apenas uma questão de ter um índice que inclua todas aswhere
colunas necessárias como suas primeiras colunas.A vantagem de um índice é o que importa.
Contanto que sua consulta seja "coberta" por uma borda principal de um índice, ela será eficiente. Os índices do banco de dados geralmente são implementados como Árvores B e a estrutura da Árvore B 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 "furos", por exemplo, se você pesquisar
ParentLogID
eDatabaseModified
, mas apenas tiver o índice ativado{ParentLogID, DateModified, Name, DatabaseModified}
, somente a{ParentLogID}
parte do índice poderá ser utilizada com eficiência.(OBSERVAÇÃO: Alguns DBMSes podem utilizar a
{DatabaseModified}
parte através de "pular varredura", mas mesmo que o DBMS faça isso, é muito menos eficiente que o acesso regular ao índice) .fonte
Columns (a, b, c, d, e, f)
e a maioria das consultas é o... WHERE A IN(...) AND B = 3
meu índice,Index(a,b,c,d)
é bom, mas não ajuda se eu tiver,... WHERE A IN (...) AND D = 5
e é por isso que o meu novo índice que eu crieiIndex(a,d)
melhorou muito o desempenho, certo?