2011-04-22 117 views
5

我有一个自连接的表。您可以将结构视为标准表来表示组织层次结构。例如表格: -为递归查询优化CTE

MemberId 
MemberName 
RelatedMemberId 

该表格由50000个样本记录组成。我写了CTE递归查询,它工作得很好。但是,在我的机器(4GB内存,2.4 Ghz Core2Duo,7200 RPM硬盘)上处理5万条记录所需的时间大约为3分钟。

我该如何提高性能,因为50000并不是那么庞大。随着时间的推移,它会不断增加。这是查询,这正是我在我的存储过程中所具有的。查询的目的是选择所有属于特定成员的成员。例如。在公司的所有者每个人都来。对于经理,除了所有者以外,所有记录都会被返回。我希望你了解查询的目的。

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 

正如你可以看到以提高性能,我还送加入在最后一步,而选择记录,使所有不必要的记录做没有插入到临时表中。如果我在CTE的基础步骤和递归步骤中加入(而不是在最后一步选择),则查询需要20分钟才能执行!

MemberId是表中的主键。

感谢提前:)

回答

8

在你的锚状况你有Where IsNull(MemberId,0) = IsNull(@MemberId,0)我想这是只是因为当你通过NULL作为参数=不带回IS NULL价值观方面的工作。这将导致扫描而不是寻找。

使用WHERE MemberId = @MemberId OR (@MemberId IS NULL AND MemberId IS NULL)代替哪个 sargable。

此外,我假设你不能有一个索引RelatedMemberId。如果你不应该添加一个

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

(虽然你可以跳过包括列位如果MemberId是因为它会自动包含聚集索引键)