目前尚不完全清楚您是要针对深度优先搜索还是广度优先搜索进行优化;问题建议深度优先,但最后的评论是关于广度优先的。
您拥有深度优先所需的所有索引(只需索引hierarchyid
柱子)。对于广度优先,仅仅create计算出的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
尝试一下 - 这应该可以解决您的性能问题。