Не е съвсем ясно дали се опитвате да оптимизирате за търсене в дълбочина или в ширина; въпросът предполага първо в дълбочина, но коментарите в края са за първо в ширина.
Имате всички индекси, от които се нуждаете за първо в дълбочина (просто индексирайте hierarchyid
колона). За широчината на първо място не е достатъчно само да творите изчисленото level
колона, трябва да я индексирате също:
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Имайте предвид, че за неклъстерирани индекси най-вероятно ще имате нужда от INCLUDE
- в противен случай SQL Server може вместо това да прибегне до сканиране на клъстерен индекс.)
Сега, ако се опитвате да намерите всички предци на възел, искате да вземете малко по-различен подход. Можете да направите тези търсения светкавично бързи, защото - и ето какво е страхотно в hierarchyid
- всеки възел вече "съдържа" всички свои предци.
Използвам CLR функция, за да направя това възможно най-бързо, но можете да го направите с рекурсивен 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
Сега, за да получите всички предшественици и потомци, използвайте го по следния начин:
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
Опитайте - това трябва да реши проблемите ви с производителността.