agr*_*ath 6 performance sql-server-2008 sql-server query-performance
我是 ac# 开发人员,但是我对 SQL 很有经验。我在优化查询方面有一些经验,但我遇到了一个让我难倒的经验。
查询大约需要 3 分钟才能运行大约 20,000 行。行立即开始流式传输,但在 3 分钟内,SQL 服务器 cpu 固定在 100%。
在这种特殊情况下,我的查询执行得很好,直到客户要求我用 20k 行测试它们。这 20k 行(客户)分布在 20 个从业者中(所以每个人大约 1000 个)
这是我的相关表的数据库架构:

该查询使用递归 CTE 来收集给定源从业者的(n 级)客户端树。然后它连接到一些 FK 类型的表以收集额外的信息。
看起来放缓来自加入权限表,权限表代表哪些从业者管理哪些客户端。
pooling.ClientAccountInheritedRateGroup,pooling.ClientAccountFirstContact并且pooling.PractitionerAccountFirstContact是所有视图,所有视图都以亚秒选择返回完整数据集。
是的,现在进行实际查询(对不起,它有点像怪物):
with h (distance, id, name, parentid, [path]) as (
select
0,
pa.id,
pa.name,
null,
convert(varchar(80), ltrim(str(pa.id))) as node_seq
from
pooling.practitioneraccount pa
left outer join pooling.practitioneraccountrelation as par
on pa.id = par.childid
where
pa.id = @PractitionerAccountId
or (@PractitionerAccountId is null and par.parentid is null)
union all
select
1,
-1,
'Unmanaged Clients',
-1,
'-1'
where @practitioneraccountid is null
union all
select
distance + 1,
pa.id,
pa.name,
par.parentid,
convert(varchar(80), h.path + ',' + ltrim(str(pa.id)))
from
pooling.practitioneraccount pa
inner join pooling.practitioneraccountrelation as par
on pa.id = par.childid
inner join h on par.parentid = h.id
)
select
distance as Depth,
h.id as PractitionerAccountId,
h.name as PractitionerAccountName,
pafc.FullName as PractitionerAccountContactName,
h.parentid as PractitionerAccountParentId,
path as PractitionerAccountPath,
ca.id as ClientAccountId,
ca.name as ClientAccountName,
ca.irdnumber as ClientAccountIrdNumber,
bd.id as ClientAccountBalanceDateId,
bd.day as ClientAccountBalanceDateDay,
bd.month as ClientAccountBalanceDateMonth,
cafc.FirstName as ClientAccountContactFirstName,
cafc.LastName as ClientAccountContactLastName,
cafc.PhoneNumber as ClientAccountContactPhoneNumber,
cafc.MobileNumber as ClientAccountContactMobileNumber,
ca.TownOrCity as ClientAccountLocation,
rr.Rate as ClientAccountRwtRate,
rr.Id as ClientAccountRwtRateId,
cairg.RateGroupId as ClientAccountInheritedRateGroupId,
cairg.RateGroupName as ClientAccountInheritedRateGroupName,
ag.id as ClientAccountAssociatedGroupId,
ag.name as ClientAccountAssociatedGroupName,
agca.uniqueid as ClientAccountAssociatedGroupUniqueId,
agca.approved as ClientAccountAssociatedGroupApproved
from
h
left outer join security.practitioneraccountauthority as paa
on (h.id = paa.practitioneraccountid)
left outer join pooling.clientaccount as ca
on (
paa.clientaccountid = ca.id
or (h.id = -1 and ca.id not in (
select clientaccountid
from security.practitioneraccountauthority
)
)
)
left outer join config.RwtRate as rr on ca.RwtRateId = rr.Id
left outer join config.balancedate as bd on (ca.balancedateid = bd.id)
left outer join pooling.ClientAccountInheritedRateGroup as cairg
on (ca.id = cairg.ClientAccountId)
left outer join security.associatedgroupclientaccount as agca
on (ca.id = agca.clientaccountid)
left outer join security.associatedgroup as ag
on (agca.associatedgroupid = ag.id)
left outer join pooling.ClientAccountFirstContact as cafc
on (cafc.ClientAccountId = ca.Id)
left outer join pooling.PractitionerAccountFirstContact as pafc
on (pafc.PractitionerAccountId = paa.PractitionerAccountId)
Run Code Online (Sandbox Code Playgroud)
查询中的 CTE 为我们提供了完整的从业者树,然后通过权限表将其连接到他们下的客户端。查询的 CTE 部分几乎立即返回,只有当我们开始加入客户端时才会出现性能问题。
我在权限表的 ClientAccountId 列上添加了一个索引(和统计信息)
CREATE NONCLUSTERED INDEX [IX_PractitionerAccountAuthority_ClientAccountId]
ON [security].[PractitionerAccountAuthority]
(
[ClientAccountId] ASC
)
Run Code Online (Sandbox Code Playgroud)
请询问您是否需要其他信息,例如上述视图的定义。
结果是这样的:
left outer join pooling.clientaccount as ca
on (
paa.clientaccountid = ca.id
or (h.id = -1 and ca.id not in (
select clientaccountid
from security.practitioneraccountauthority
)
)
)
Run Code Online (Sandbox Code Playgroud)
导致速度大幅下降的原因是 on 条件根据输入数据有多个路径,因此无法优化。
| 归档时间: |
|
| 查看次数: |
3927 次 |
| 最近记录: |