2011-04-22 52 views
5

Tôi có một bảng tự tham gia. Bạn có thể nghĩ cấu trúc như là bảng tiêu chuẩn để biểu diễn cấu trúc phân cấp của tổ chức. Ví dụ: bảng: -Tối ưu hóa CTE cho các truy vấn đệ quy

MemberId 
MemberName 
RelatedMemberId 

Bảng này bao gồm 50000 bản ghi mẫu. Tôi đã viết CTE đệ quy truy vấn và nó hoạt động hoàn toàn tốt. Tuy nhiên thời gian cần để xử lý chỉ 50000 hồ sơ là vòng khoảng 3 phút trên máy tính của tôi (4GB Ram, 2,4 Ghz Core2Duo, 7200 RPM HDD).

Làm cách nào tôi có thể cải thiện hiệu suất vì 50000 không phải là số quá lớn. Theo thời gian nó sẽ tiếp tục tăng lên. Đây là truy vấn mà là chính xác những gì tôi có trong thủ tục lưu trữ của tôi. Mục đích của truy vấn là chọn tất cả các thành viên đi theo một thành viên cụ thể. Ví dụ. Dưới chủ sở hữu của công ty mỗi và mọi người đến. Đối với người quản lý, ngoại trừ chủ sở hữu tất cả các hồ sơ được trả về. Tôi hy vọng bạn hiểu mục đích của truy vấn.

SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO

Alter PROCEDURE spGetNonVirtualizedData 
(
    @MemberId int 
) 
AS 
BEGIN 

    With MembersCTE As 
    (
     Select parent.MemberId As MemberId, 0 as Level 
      From Members as parent Where IsNull(MemberId,0) = IsNull(@MemberId,0) 

        Union ALL 
     Select child.MemberId As MemberId , Level + 1 as Level 
      From Members as child 
       Inner Join MembersCTE on MembersCTE.MemberId = child.RelatedMemberId 
    ) 
    Select Members.* 
     From MembersCTE 
     Inner Join Members On MembersCTE.MemberId = Members.MemberId 
     option(maxrecursion 0) 

END 
GO 

Như bạn thấy để cải thiện hiệu suất, tôi thậm chí đã tham gia ở bước cuối cùng trong khi lựa chọn hồ sơ để tất cả hồ sơ không cần thiết làm không được đưa vào bảng tạm thời. Nếu tôi tham gia vào bước cơ sở của tôi và bước đệ quy của CTE (thay vì Chọn ở bước cuối cùng), truy vấn sẽ mất 20 phút để thực thi!

MemberId là khóa chính trong bảng.

Cảm ơn trước :)

Trả lời

8

Trong điều kiện neo của bạn, bạn có Where IsNull(MemberId,0) = IsNull(@MemberId,0) Tôi giả định này chỉ là bởi vì khi bạn vượt qua NULL như một tham số = không hoạt động về mặt mang lại IS NULL giá trị. Điều này sẽ gây ra một lần quét thay vì tìm kiếm.

Sử dụng WHERE MemberId = @MemberId OR (@MemberId IS NULL AND MemberId IS NULL) thay vì đó sargable.

Ngoài ra tôi giả định rằng bạn không thể có chỉ mục trên RelatedMemberId. Nếu không, bạn nên thêm một

CREATE NONCLUSTERED INDEX ix_name ON Members(RelatedMemberId) INCLUDE (MemberId) 

(mặc dù bạn có thể bỏ qua chút cột bao gồm nếu MemberId là chìa khóa clustered index vì nó sẽ được bao gồm tự động)

Các vấn đề liên quan