Tenho a seguinte tabela no meu banco de dados:
create table [dbo].[tb_StatusLog](
[RequestID] [int] not null,
[statusID] [int] not null,
[startTime] [datetime] not null,
[endTime] [datetime] null,
)
com o seguinte índice não agrupado
create nonclusteredindex [index1] on [dbo].[tb_StatusLog]
(
requestID asc,
statusID asc
)
include ([startTime])
e a seguinte função com valor de tabelafn_getTable
select requestID, max(startTime)
from tb_StatusLog
where statusID=2
group by requestID, statusID
depois de executar o profiler trace e executar os resultados pelo db engine tuning advisor, ele propôs que eu criasse o seguinte índice (que é o mesmo índice que tenho, mas com as colunas de chave invertidas):
create nonclusteredindex [index2] on [dbo].[tb_StatusLog]
(
statusID asc,
requestID asc
)
include ([startTime])
Agora, ao executar fn_getTable
, o plano de execução usa index2
em vez de index1
e o desempenho é aprimorado.
Por que é que?
Porque você tem um predicado de igualdade em
where statusID=2
.Com a ordem inversa, é capaz de buscar exatamente as linhas que correspondem ao status e estas podem então alimentar um agregado de fluxo para fazer o agrupamento.
Seu índice original suporta o
group by requestID, statusID
mas não oWHERE
- o que significa que todo o índice precisará ser verificado e apenas as linhas correspondentes aostatusID=2
retido.Um pouco simplificado, mas você pode pensar em um índice composto como se as linhas fossem ordenadas primeiro pela primeira coluna, depois pela segunda coluna e assim por diante. Seu primeiro exemplo seria:
Para encontrar linhas com statusId=2, não há como dizer por onde começar, todo o índice deve ser verificado. Compare com:
O SGBD pode começar com (2,A), ler outra entrada (2,B) e terminar com ela.