Det er ikke helt klart, om du forsøger at optimere til dybde-først eller bredde-først søgning; spørgsmålet antyder dybde først, men kommentarerne til sidst handler om bredden først.
Du har alle de indekser, du har brug for til depth-first (bare indekser hierarchyid
kolonne). For bredden først er det ikke nok bare at oprette det beregnede level
kolonne, skal du også indeksere den:
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Bemærk, at for ikke-klyngede indekser vil du højst sandsynligt have brug for INCLUDE
- Ellers kan SQL Server ty til at lave en klynget indeksscanning i stedet.)
Hvis du nu prøver at finde alle forfædre af en node, vil du tage en lidt anden vinkel. Du kan gøre disse søgninger lynhurtige, fordi - og her er det fede ved hierarchyid
- hver node "indeholder" allerede alle sine forfædre.
Jeg bruger en CLR-funktion til at gøre dette så hurtigt som muligt, men du kan gøre det med en rekursiv 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, for at få alle forfædre og efterkommere, brug det sådan her:
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
Prøv det - dette burde løse dine præstationsproblemer.