Tidak sepenuhnya jelas apakah Anda mencoba mengoptimalkan penelusuran yang mengutamakan kedalaman atau keluasan terlebih dahulu; pertanyaannya menyarankan yang mendalam terlebih dahulu, tetapi komentar di bagian akhir adalah tentang yang luas terlebih dahulu.
Anda memiliki semua indeks yang Anda butuhkan untuk depth-first (cukup indeks hierarchyid
kolom). Untuk keluasan-pertama, tidak cukup hanya dengan membuat level
yang dihitung kolom, Anda harus mengindeksnya juga:
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Perhatikan bahwa untuk indeks yang tidak berkerumun kemungkinan besar Anda memerlukan INCLUDE
- jika tidak, SQL Server dapat melakukan pemindaian indeks berkerumun sebagai gantinya.)
Sekarang, jika Anda mencoba menemukan semua leluhur dari sebuah node, Anda ingin mengambil taktik yang sedikit berbeda. Anda dapat melakukan penelusuran ini secepat kilat, karena - dan inilah yang keren dari hierarchyid
- setiap simpul sudah "berisi" semua leluhurnya.
Saya menggunakan fungsi CLR untuk membuat ini secepat mungkin, tetapi Anda dapat melakukannya dengan CTE rekursif:
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
Sekarang, untuk mendapatkan semua leluhur dan keturunan, gunakan seperti ini:
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
Cobalah - ini akan menyelesaikan masalah kinerja Anda.