Není zcela jasné, zda se snažíte optimalizovat pro vyhledávání do hloubky nebo do šířky; otázka naznačuje nejprve hloubku, ale komentáře na konci jsou o šířce.
Máte všechny indexy, které potřebujete pro hloubku na prvním místě (stačí indexovat hierarchyid
sloupec). Pokud jde o šířku, nestačí jen vytvářet vypočítanou level
musíte také indexovat:
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Uvědomte si, že pro indexy bez klastrů budete s největší pravděpodobností potřebovat INCLUDE
- V opačném případě se SQL Server může uchýlit k provedení skenování clusterového indexu.)
Nyní, pokud se snažíte najít všechny předky uzlu, chcete zvolit trochu jiný směr. Tato vyhledávání můžete provést bleskově, protože – a zde je to, co je skvělé na hierarchyid
- každý uzel již "obsahuje" všechny své předky.
Používám funkci CLR, abych to udělal co nejrychleji, ale můžete to udělat pomocí rekurzivního 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
Nyní, abyste získali všechny předky a potomky, použijte to takto:
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
Vyzkoušejte to – to by mělo vyřešit vaše problémy s výkonem.