A estrutura das minhas tabelas está abaixo:
TbDoc (ID int , ...)
TbDocActions( ID Int, DocID Int, Date DateTime, col1 int, col2 int, ...)
Eu quero ter uma visão indexada para obter as últimas colunas TbDocActions para cada TbDoc
registro. resultado desta visão deve ser como abaixo:
DocID , col1, col2, ...
Para obter este resultado com visualização, posso usar a consulta abaixo:
Select Z.DocID, X.*
From (Select DocID, Max(ID) as MaxActionID
From TbDocActions
Group By DocID
)Z
inner join TbDocActions X ON X.ID = Z.MaxActionID
mas quero que a exibição indexada tenha melhor desempenho. e na exibição indexada não posso usar Max()
a função agregada.
Como você já sabe, não é possível usar um
MAX()
agregado em uma exibição indexada. De qualquer forma, não se engane acreditando que criar uma exibição indexada é um botão liga/desliga mágico de desempenho. Dependendo de sua carga de trabalho, manter a exibição indexada pode custar mais desempenho do que você ganha com as consultas feitas nela.Algumas alternativas podem ser:
(1) crie um índice não clusterizado
dbo.TbDocActions(DocID, ID DESC)
ou solte o índice clusterizado existente e altere-o paraDocID, ID DESC
. (SeID
for uma coluna de identidade, você provavelmente também a configurou para ser a chave primária e será agrupada por padrão, mas não precisa ser o caso.)(2) mantenha uma tabela separada com o
DocID
como a chave primária e mantenha o maisID
alto atualizado usando gatilhos (ou um procedimento armazenado se você estiver restringindo as gravações apenas aos procedimentos armazenados). Você terá que ter lógica para todos os três tipos de DML (insert
,update
edelete
) porque, em teoria, qualquer um deles pode afetar oMAX
cálculo. (Menos risco, obviamente, se ambas asID
colunas foremIDENTITY
.) Você também pode adicionar uma coluna à tabela principal e mantê-la atualizada da mesma maneira.Observe que as mesmas ressalvas se aplicam - adicionar índices ou manter valores em outras tabelas pode beneficiar essa consulta específica, mas não são mágicas - podem afetar outras partes de sua carga de trabalho. Você deve sempre levar em consideração todo o seu ciclo de negócios ao pensar em "consertar" qualquer consulta única...
A solução mais rápida é a seguinte: você cria uma coluna adicional, IsLastID, e cria um índice filtrado ou uma exibição indexada usando-a. Você pode usar restrições para garantir a integridade de IsLastID, conforme descrito aqui
Grant Fritchey escreveu uma comparação detalhada de várias soluções aqui