Det är inte helt klart om du försöker optimera för djup-först eller bredd-först sökning; frågan antyder djupet först, men kommentarerna i slutet handlar om bredden först.
Du har alla index du behöver för depth-first (indexera bara hierarchyid
kolumn). För bredd-först räcker det inte bara att skapa den beräknade level
kolumn, måste du indexera den också:
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Observera att för icke-klustrade index kommer du sannolikt att behöva INCLUDE
- annars kan SQL Server tillgripa att göra en klustrad indexsökning istället.)
Nu, om du försöker hitta alla förfäder av en nod vill du ta ett lite annorlunda grepp. Du kan göra dessa sökningar blixtsnabbt, eftersom - och här är vad som är coolt med hierarchyid
- varje nod "innehåller" redan alla sina förfäder.
Jag använder en CLR-funktion för att göra detta så snabbt som möjligt, men du kan göra 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, för att få alla förfäder och ättlingar, använd det så här:
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
Testa det - det här borde lösa dina prestandaproblem.