优化CTE以进行递归查询

TCM*_*TCM 6 sql sql-server-2005 sql-server-2008

我有一张自我加入的桌子.您可以将结构视为标准表来表示组织层次结构.如表: -

MemberId
MemberName
RelatedMemberId
Run Code Online (Sandbox Code Playgroud)

该表包含50000个样本记录.我写了CTE递归查询,它的工作非常好.然而,在我的机器上处理仅50000条记录所需的时间约为3分钟(4GB Ram,2.4 Ghz Core2Duo,7200 RPM HDD).

如何才能提高性能,因为50000不是那么庞大的数字.随着时间的推移,它将继续增加.这是我的存储过程中的查询.查询的目的是选择属于特定成员的所有成员.例如.在公司的所有者之下,每个人都来了.对于Manager,除了所有者返回所有记录.我希望你理解查询的目的.

设置ANSI_NULLS开启GO SET QUOTED_IDENTIFIER

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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,为了提高性能,我甚至在选择记录时最后一步创建了连接,以便不会将所有不必要的记录插入到临时表中.如果我在我的基本步骤和CTE的递归步骤(而不是在最后一步中选择)进行连接,则查询需要20分钟才能执行!

MemberId是表中的主键.

提前致谢 :)

Mar*_*ith 9

在你的锚条件中你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)
Run Code Online (Sandbox Code Playgroud)

(尽管您可以跳过包含的列位,如果MemberId是聚簇索引键,因为它将自动包含)