优化递归查询的 CTE

发布于 2024-11-03 01:20:49 字数 1231 浏览 1 评论 0原文

我有一张带有自连接的桌子。您可以将结构视为表示组织层次结构的标准表。例如表:-

MemberId
MemberName
RelatedMemberId

该表由 50000 条样本记录组成。我写了 CTE 递归查询,它工作得很好。然而,在我的机器(4GB RAM、2.4 Ghz Core2Duo、7200 RPM HDD)上处理 50000 条记录所需的时间约为 3 分钟。

我怎样才能提高性能,因为 50000 并不是一个很大的数字。随着时间的推移,它会不断增加。这正是我的存储过程中的查询。该查询的目的是选择特定成员下的所有成员。例如。每个人都在公司所有者的领导下。对于管理者,除了所有者之外,所有记录都会被返回。我希望您了解查询的目的。

设置 ANSI_NULLS 为开 去 将 QUOTED_IDENTIFIER 设置为 ON 正如

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 是表中的主键。

提前致谢 :)

I have a table with self join. You can think of the structure as standard table to represent organisational hierarchy. Eg table:-

MemberId
MemberName
RelatedMemberId

This table consists of 50000 sample records. I wrote CTE recursive query and it works absolutely fine. However the time it takes to process just 50000 records is round about 3 minutes on my machine (4GB Ram, 2.4 Ghz Core2Duo, 7200 RPM HDD).

How can I possibly improve the performance because 50000 is not so huge number. Over time it will keep on increasing. This is the query which is exactly what I have in my Stored Procedure. The query's purpose is to select all the members that come under a specific member. Eg. Under Owner of the company each and every person comes. For Manager, except Owner all of the records gets returned. I hope you understand the query's purpose.

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

As you can see to improve the performance, I have even made the Joins at the last step while selecting records so that all unnecessary records do not get inserted into temp table. If I made joins in my base step and recursive step of CTE (instead of Select at the last step) the query takes 20 minutes to execute!

MemberId is primary key in the table.

Thanks in advance :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

泛滥成性 2024-11-10 01:20:49

在您的锚条件中,您有 Where IsNull(MemberId,0) = IsNull(@MemberId,0) 我认为这只是因为当您将 NULL 作为参数传递时 = 无法返回 IS NULL 值。这将导致扫描而不是查找。

使用 WHERE MemberId = @MemberId OR (@MemberId IS NULL AND MemberId IS NULL) 来代替可控制的。

另外,我假设您无法在 RelatedMemberId 上建立索引。如果不是,您应该添加一个

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

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

In your anchor condition you have Where IsNull(MemberId,0) = IsNull(@MemberId,0) I assume this is just because when you pass NULL as a parameter = doesn't work in terms of bringing back IS NULL values. This will cause a scan rather than a seek.

Use WHERE MemberId = @MemberId OR (@MemberId IS NULL AND MemberId IS NULL) instead which is sargable.

Also I'm assuming that you can't have an index on RelatedMemberId. If not you should add one

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

(though you can skip the included column bit if MemberId is the clustered index key as it will be included automatically)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文