Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Pergunta sobre o desempenho em profundidade do SQL Server HierarchyID


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.