我在Microsoft SQL Server上执行查询的速度很慢。以下是查询和执行计划:https://www.brentozar.com/pastetheplan/?id=BJUrHRwng
查询非常慢:
Table 'Worktable'. Scan count 30, logical reads 184041, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'SiteVersions'. Scan count 1, logical reads 363, physical reads 0, read-ahead reads 351, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#BB50937F'. Scan count 1, logical reads 5979, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'AllWebs'. Scan count 11, logical reads 3041, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'AllSites'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
SQL Server Execution Times:
CPU time = 715296 ms, elapsed time = 873728 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
这是在双Intel(R)Xeon(R)CPU E5-2680 0 @ 2.70GHz,2700 Mhz,8 Core(s),16 Logical Processor(s)系统上。查询以max-dop为1执行。
实际执行计划表明特定排序操作具有最大的估计成本,并且没有返回极大行数的操作。
但是,当我检查实际执行计划时,我发现排序操作不太可能导致所有CPU负载。例如,当我在单独的独立查询中执行排序操作时,速度非常快。
我怀疑合并连接是性能杀手:它连接两个平均大的行集(分别为29840和9557行),导致可能存在大量连接的行。它有一个非常非常严格的WHERE子句和一个昂贵的RESIDUAL操作,需要为每个剩余行评估几个函数。但是,我无法支持我对实际数字的怀疑。
因此,我有几个问题,所以我可以证实我的怀疑:
问候,节拍
答案 0 :(得分:0)
我不会太担心您看到的CPU成本,它们只是一个指标,可以让您了解CPU从查询中获得的压力。在这种情况下,我认为CPU成本是由查询的复杂性引起的,子查询中的rank()和where子句中的函数。
我会尝试在几个逻辑部分中拆分您的查询,以帮助查询优化器找出最佳计划并使用中间结果改进它的工作:
select SiteId
, WebId
, VersionId
, Version
, rank() over (partition by SiteId, WebId, VersionId order by Id desc) as Rank
into #tempSiteVersions
from SiteVersions;
with cteFirstRankingSites as
(
select SV.SiteId
, S.PlatformVersion
, SV.Version
, SSV.ApplicableWebTemplate
, W.WebTemplate
, SSV.PreviousTargetVersionNumber
, SSV.TargetVersionNumber
from #tempSiteVersions as SV
join TVF_Webs_NoLock_ALL() as W on W.SiteId = SV.SiteId
join Sites as S with (nolock) on W.SiteId = S.Id
join @SiteSequenceVersions as SSV on SV.VersionId = SSV.Id
where SV.Rank = 1
)
select distinct
SiteId
from [cteFirstRankingSites] as frs
where (
(
(dbo.fn_ConvertVersionToNumber(frs.PlatformVersion) < 15000000000000)
and (dbo.fn_ConvertVersionToNumber(frs.Version) < frs.PreviousTargetVersionNumber)
)
or (
(dbo.fn_ConvertVersionToNumber(frs.PlatformVersion) >= 15000000000000)
and (dbo.fn_ConvertVersionToNumber(frs.Version) < frs.TargetVersionNumber)
)
)
and (
frs.ApplicableWebTemplate = 0
or frs.ApplicableWebTemplate = frs.WebTemplate
)
由于我没有可用的实际表格和函数,因此可能存在语法错误,但您明白了。
答案 1 :(得分:0)
有没有办法从SQL Server获取每个物理操作报告的实际CPU成本?
您可以使用下面的Set Statistics配置文件,它会单独报告每个逻辑运算符,否则您可以右键单击逻辑运算符以查看成本
选项1:
在上设置统计资料 你的查询
选项3:
适用于2016 sp1,您可以使用DMV以下,但您必须在查询前附加set statistics profile
通过这种方式,您可以跟踪实时统计信息和更多信息
select
session_id,physical_operator_name,
row_count,actual_read_row_count,estimate_row_count,estimated_read_row_count,
rebind_count,
rewind_count,
scan_count,
logical_read_count,
physical_read_count,
logical_read_count
from
sys.dm_exec_query_profiles
where session_id=55;
是否有办法报告执行的RESIDUAL操作的实际数量和/或合并连接操作中WHERE子句后剩余的行数?
这已在SQLServer中实现,但为了显示这一点,您必须使用SSMS 2016并且版本大于SQL2012 sp3,(我在2016年sp1,我可以看到,不确定2014年)。参见下文我机器的截图..
有没有办法估算与184041报告的“工作台”逻辑读取相关的CPU成本?
工作台将与操作员相关联,因此跟踪操作员将为您提供操作员的费用
有没有办法找出哪个物理操作使用'工作台'
主要是排序操作员使用工作表。在您的情况下,它是具有排序警告的操作员
有关修复查询的建议很少:
1。)我在Partition by query中看到排序运算符的成本为73%,因此我建议使用以下索引来排除排序。此索引仅适用于此查询
create index nci_somename on siteversions
(siteid,webid,versionid,id desc)
include(version)
另外我建议将上面的输出插入到派生表中,如果表很大,那么SQL可以有正确的统计信息
2.)所有网站列显示统计信息警告,尝试更新该表的统计信息或手动创建一个
3.)您的谓词如下所示
dbo.fn_ConvertVersionToNumber(S.PlatformVersion) < 15000000000000)
这些类型的谓词根本不会被攻击。重写它们