Il n'est pas tout à fait clair si vous essayez d'optimiser la recherche en profondeur d'abord ou en largeur d'abord; la question suggère la profondeur d'abord, mais les commentaires à la fin concernent la largeur d'abord.
Vous avez tous les index dont vous avez besoin pour la profondeur d'abord (indexez simplement le hierarchyid
colonne). Pour la largeur d'abord, il ne suffit pas de créer le level
calculé colonne, vous devez également l'indexer :
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Notez que pour les index non clusterisés, vous aurez probablement besoin du INCLUDE
- sinon, SQL Server peut avoir recours à une analyse d'index cluster à la place.)
Maintenant, si vous essayez de trouver tous les ancêtres d'un nœud, vous voulez prendre une approche légèrement différente. Vous pouvez rendre ces recherches ultra-rapides, car - et voici ce qui est cool avec hierarchyid
- chaque nœud "contient" déjà tous ses ancêtres.
J'utilise une fonction CLR pour rendre cela aussi rapide que possible, mais vous pouvez le faire avec un CTE récursif :
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
Maintenant, pour obtenir tous les ancêtres et descendants, utilisez-le comme ceci :
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
Essayez-le - cela devrait résoudre vos problèmes de performances.