Không hoàn toàn rõ ràng là bạn đang cố gắng tối ưu hóa cho tìm kiếm theo chiều sâu hay theo chiều rộng; câu hỏi gợi ý về chiều sâu trước tiên, nhưng các nhận xét ở cuối là về chiều rộng ưu tiên.
Bạn có tất cả các chỉ mục bạn cần để tìm hiểu sâu (chỉ cần lập chỉ mục hierarchyid
cột). Đối với bề rộng, ưu tiên hàng đầu, chỉ tạo là chưa đủ level
được tính toán , bạn cũng phải lập chỉ mục nó:
ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()
CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)
(Lưu ý rằng đối với các chỉ mục không phân cụm, rất có thể bạn sẽ cần INCLUDE
- nếu không, SQL Server có thể dùng đến việc quét chỉ mục theo cụm để thay thế.)
Bây giờ, nếu bạn đang cố gắng tìm tất cả tổ tiên của một nút, bạn muốn thực hiện một cách xử lý hơi khác. Bạn có thể thực hiện các tìm kiếm này nhanh như chớp, bởi vì - và đây là những điều thú vị về hierarchyid
- mỗi nút đã "chứa" tất cả các tổ tiên của nó.
Tôi sử dụng hàm CLR để thực hiện điều này nhanh nhất có thể, nhưng bạn có thể thực hiện điều này với CTE đệ quy:
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
Bây giờ, để có được tất cả tổ tiên và con cháu, hãy sử dụng nó như thế này:
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
Hãy dùng thử - điều này sẽ giải quyết các vấn đề về hiệu suất của bạn.