Nie jest do końca jasne, czy próbujesz zoptymalizować wyszukiwanie w głąb czy wszerz; pytanie sugeruje najpierw w głąb, ale komentarze na końcu dotyczą przede wszystkim wszerz.
Masz wszystkie indeksy, których potrzebujesz na pierwszym miejscu (po prostu zindeksuj hierarchyid
kolumna). Po pierwsze, nie wystarczy tylko tworzyć obliczony level
kolumna, musisz ją również zindeksować:
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Zauważ, że dla indeksów nieklastrowych najprawdopodobniej będziesz potrzebować INCLUDE
- w przeciwnym razie SQL Server może zamiast tego użyć skanowania indeksu klastrowego.)
Teraz, jeśli próbujesz znaleźć wszystkich przodków węzła, chcesz przyjąć nieco inną taktykę. Możesz sprawić, że te wyszukiwania będą błyskawiczne, ponieważ - i oto, co jest fajnego w hierarchyid
- każdy węzeł już "zawiera" wszystkich swoich przodków.
Używam funkcji CLR, aby zrobić to tak szybko, jak to możliwe, ale możesz to zrobić z rekurencyjnym 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
Teraz, aby uzyskać wszystkich przodków i potomków, użyj go w ten sposób:
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
Wypróbuj - to powinno rozwiązać Twoje problemy z wydajnością.