Não está totalmente claro se você está tentando otimizar para busca em profundidade ou em largura; a pergunta sugere profundidade primeiro, mas os comentários no final são sobre amplitude.
Você tem todos os índices necessários para a profundidade (basta indexar o
hierarchyid
coluna). Para a amplitude, não basta criar o level
calculado coluna, você tem que indexá-lo também:ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Observe que para índices não clusterizados, você provavelmente precisará do
INCLUDE
- caso contrário, o SQL Server pode recorrer a uma verificação de índice clusterizado.) Agora, se você está tentando encontrar todos os ancestrais de um nó, você quer tomar um rumo ligeiramente diferente. Você pode fazer essas pesquisas rapidamente, porque - e aqui está o que é legal sobre
hierarchyid
- cada nó já "contém" todos os seus ancestrais. Eu uso uma função CLR para tornar isso o mais rápido possível, mas você pode fazer isso com um CTE recursivo:
CREATE FUNCTION dbo.GetAncestors
(
@h hierarchyid
)
RETURNS TABLE
AS RETURN
WITH Hierarchy_CTE AS
(
SELECT @h AS id
UNION ALL
SELECT h.id.GetAncestor(1)
FROM Hierarchy_CTE h
WHERE h.id <> hierarchyid::GetRoot()
)
SELECT id FROM Hierarchy_CTE
Agora, para obter todos os ancestrais e descendentes, use-o assim:
DECLARE @MessageID hierarchyID /* passed in from application */
SELECT m.MessageID, m.MessageComment
FROM Message as m
WHERE m.MessageId.IsDescendantOf(@MessageID) = 1
OR m.MessageId IN (SELECT id FROM dbo.GetAncestors(@MessageID.GetAncestor(1)))
ORDER BY m.MessageID
Experimente - isso deve resolver seus problemas de desempenho.