我有一张自我加入的桌子。您可以将结构视为标准表来表示组织层次结构。例如表: -
MemberId
MemberName
RelatedMemberId
此表包含50000个样本记录。我写了CTE递归查询,它的工作非常好。然而,在我的机器上处理仅50000条记录所需的时间约为3分钟(4GB Ram,2.4 Ghz Core2Duo,7200 RPM HDD)。
我怎样才能提高性能,因为50000并不是那么庞大。随着时间的推移,它将继续增加。这是我的存储过程中的查询。查询的目的是选择属于特定成员的所有成员。例如。在公司的所有者之下,每个人都来了。对于Manager,除了所有者返回所有记录。我希望你理解查询的目的。
SET ANSI_NULLS ON 走 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是表中的主键。
提前致谢:)
答案 0 :(得分:9)
在您的锚定状态下,您有Where IsNull(MemberId,0) = IsNull(@MemberId,0)
我认为这只是因为当您将NULL
作为参数=
传递时,IS NULL
无法恢复WHERE MemberId = @MemberId OR (@MemberId IS NULL AND MemberId IS NULL)
值。这将导致扫描而不是搜索。
使用RelatedMemberId
代替 sargable。
另外我假设你不能在CREATE NONCLUSTERED INDEX ix_name ON Members(RelatedMemberId) INCLUDE (MemberId)
上有索引。如果没有,你应该添加一个
MemberId
(尽管如果{{1}}是聚集索引键,您可以跳过包含的列位,因为它将自动包含在内)