Het is niet helemaal duidelijk of je probeert te optimaliseren voor diepte-eerst of breedte-eerst zoeken; de vraag suggereert eerst de diepte, maar de opmerkingen aan het einde gaan over de breedte eerst.
Je hebt alle indexen die je nodig hebt voor depth-first (indexeer gewoon de hierarchyid
kolom). Voor de breedte is het niet genoeg om alleen maar te maken het berekende level
kolom, moet u deze ook indexeren:
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Houd er rekening mee dat u voor niet-geclusterde indexen hoogstwaarschijnlijk de INCLUDE
nodig hebt - anders kan SQL Server in plaats daarvan een geclusterde indexscan uitvoeren.)
Als u nu alle voorouders probeert te vinden, van een knooppunt, wilt u een iets andere overstag gaan. U kunt deze zoekopdrachten razendsnel uitvoeren, want - en dit is het leuke van hierarchyid
- elk knooppunt "bevat" al zijn voorouders.
Ik gebruik een CLR-functie om dit zo snel mogelijk te doen, maar je kunt het doen met een recursieve CTE:
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
Nu, om alle voorouders en afstammelingen te krijgen, gebruik het als volgt:
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
Probeer het uit - dit zou uw prestatieproblemen moeten oplossen.