Es ist nicht ganz klar, ob Sie versuchen, für die Tiefensuche oder die Breitensuche zu optimieren. Die Frage suggeriert Tiefe-zuerst, aber die Kommentare am Ende beziehen sich auf die Breite-zuerst.
Sie haben alle Indizes, die Sie für die Tiefensuche benötigen (indizieren Sie einfach die hierarchyid
Säule). Für die Breite zuerst reicht es nicht aus, nur zu erstellen das berechnete level
Spalte, müssen Sie diese ebenfalls indizieren:
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Beachten Sie, dass Sie für nicht geclusterte Indizes höchstwahrscheinlich den INCLUDE
benötigen - Andernfalls kann SQL Server stattdessen auf einen Clustered-Index-Scan zurückgreifen.)
Nun, wenn Sie versuchen, alle Vorfahren zu finden eines Knotens möchten Sie einen etwas anderen Weg einschlagen. Sie können diese Suchen blitzschnell durchführen, denn - und hier ist das Coole an hierarchyid
- jeder Knoten "enthält" bereits alle seine Vorfahren.
Ich verwende eine CLR-Funktion, um dies so schnell wie möglich zu machen, aber Sie können es mit einem rekursiven CTE tun:
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
Um nun alle Vorfahren und Nachkommen zu erhalten, verwenden Sie es wie folgt:
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
Probieren Sie es aus - dies sollte Ihre Leistungsprobleme lösen.