如何诊断高扫描计数

时间:2017-08-07 16:12:33

标签: sql-server

我很好奇如何在永久和临时表中诊断高扫描计数。我在运行存储过程时打开了统计信息,我试图弄清楚为什么扫描计数如此之高。我有实际的查询计划,SSMS已经建议添加一些丢失的索引,但此时没有别的。我可以研究哪些策略来诊断这些问题?

https://www.brentozar.com/pastetheplan/?id=HksFRMLw-

SQL Server Execution Times:
CPU time = 0 ms,  elapsed time = 0 ms.
Table 'disbursement_check'. Scan count 9, logical reads 2281, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'cif'. Scan count 9, logical reads 490, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'voucher'. Scan count 9, logical reads 3067, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'cif_loan_relationship'. Scan count 9, logical reads 890, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'loanacct'. Scan count 45, logical reads 44124, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'loanacct_trans_history'. Scan count 1166870, logical reads 3654129, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#B17AB456'. Scan count 8, logical reads 1180568, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#BAD74620'. Scan count 2423794, logical reads 2486442, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#BBCB6A59'. Scan count 62661, logical reads 125306, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'loan_class'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'lookup_table'. Scan count 2, logical reads 6, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'loanacct_detail'. Scan count 9, logical reads 1348, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
CPU time = 59160 ms,  elapsed time = 9877 ms.
Table '#TargetTransactions_________________________________________________________________________________________________0000000019E6'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

2 个答案:

答案 0 :(得分:0)

很棒的问题。

根据一些统计数据,我倾向于认为有一些索引或缺少索引,这些都是错误的。查询计划可能会有所启发,但截至发布时我还没有。

我认为假设loanacct_trans_history表是建议索引的表是安全的。此外,3个临时表似乎也做了相当多的工作......

以下链接有助于指导您充分了解索引以回答您的问题。

  

请参阅这个免费的90分钟网络研讨会,来自世界级的DBA,Brent Ozar:https://www.brentozar.com/archive/2016/10/think-like-engine-class-now-free-open-source/

答案 1 :(得分:0)

  

我正在试图找出扫描计数如此之高的原因。

  

表'loanacct_trans_history'。扫描计数1166870,逻辑读取   3654129,物理读取0,预读读取0,lob逻辑读取0,   lob物理读取0,lob预读读取0.表'#B17AB456'。扫描   计数8,逻辑读取1180568,物理读取0,预读读取0,   lob逻辑读取0,lob物理读取0,lob预读读取0。

因为我们没有(还有)实际执行计划,最佳假设是

[1]有一些Index Seek生成的大量范围扫描(很可能)具有大量Execution Count(可能被FORCESEEK表提示强制)

[2]和/或通过以下操作符组合生成的范围扫描或完整扫描

... - Nested Loops (Join) - Any Data Access Operator
           |
           ---------------- Index Seek / *Scan loanacct_trans_history 

在这种情况下,我假设 Estimated execution count是1,实际/真实Execution Count是高。

[3]来自执行计划的裁剪,演示了点[1]和[2],并与表loanacct_trans_history上的高扫描计数相关:

  

表'loanacct_trans_history'。扫描计数1166870,...

enter image description here

以下语句似乎会产生这种高扫描次数:

INSERT INTO #TargetTransactions (Id, CreditServiceFeeTransactionId, CustomerCifNo, VoucherId)
 SELECT mt.transrefno, rt.CreditServiceFeeTransactionId, contact.cifno, rt.VoucherId
 FROM dbo.getMyTransactions
 (
 @AssignedDealerIds,
 @DealerIds
 ) mt
 JOIN loanacct_trans_history th ON th.transrefno = mt.transrefno
...

几个简单的解决方案:在本声明的最后,我会尝试添加以下查询提示:

INSERT #T...
SELECT ...
...
OPTION(HASH JOIN)
-- Or OPTION(MERGE JOIN)
-- Or OPTION(HASH JOIN, MERGE JOIN)