Ian*_*oyd 12 sql-server sql-server-2012
我一直在尝试诊断应用程序中的减速。为此,我记录了 SQL Server扩展事件。
存储过程的执行时间变化很大。这个存储过程的很多执行在 < 1s 内返回:
而对于那个“快速”的bucket,它的时间远小于1s。它实际上是大约 90 毫秒:
但是有一个长尾用户必须等待 2s、3s、4s 秒。有些必须等待 12 秒、13 秒、14 秒。然后是真正可怜的灵魂,他们必须等待 22 秒、23 秒、24 秒。
30 秒后,客户端应用程序放弃,中止查询,用户不得不等待30 秒。
所以我试图关联:
而且似乎没有任何相关性;似乎没有一个原因
持续时间 vs 逻辑读取:无论是少量还是大量的逻辑读取,持续时间仍然波动很大:
持续时间 vs 物理读取:即使查询不是从缓存中提供的,并且需要大量物理读取,它也不会影响持续时间:
持续时间 vs cpu 时间:无论查询占用 0 秒的 CPU 时间,还是完整的 2.5 秒的 CPU 时间,持续时间都具有相同的可变性:
奖励:我注意到Duration v Physical Reads和Duration v CPU 时间看起来非常相似。如果我尝试将 CPU 时间与物理读取相关联,就会证明这一点:
事实证明,大量 CPU 使用来自 I/O。谁知道!
因此,如果执行查询的行为无法解释执行时间的差异,是否意味着它与 CPU 或硬盘驱动器无关?
如果我们假设瓶颈是 CPU;该服务器的 CPU 供电不足:
硬盘驱动器也是如此。如果我们假设硬盘是一个瓶颈;硬盘驱动器没有足够的随机吞吐量用于此服务器:
存储过程本身既不执行也不要求任何写入。
所以它不像是在返回大量的数据。
服务器的处理器使用率平均约为 1.8%,偶尔会高达 18% - 因此 CPU 负载似乎不是问题:
所以服务器 CPU 似乎没有过载。
但是服务器是虚拟的...
我能想象的唯一剩下的就是存在于服务器宇宙之外的东西。
它不像是存储过程的参数(因为手动发出相同的查询并且不需要 27 秒 - 需要大约 0 秒)。
还有什么可以解释服务器有时需要 30 秒而不是 0 秒来运行相同的编译存储过程。
这是一个虚拟服务器
浏览服务器的扩展事件;当查询突然需要 20 秒时,没有其他特别的事情发生。它运行良好,然后决定不正常运行:
而且我找不到其他特别费劲的东西。它不是在每 2 小时事务日志备份期间。
还有什么会是什么?
除了“服务器”之外,我还有什么可以说的吗?
我意识到我已经将持续时间与所有内容相关联:
但我没有将它与一天中的时间相关联的一件事。也许每 2 小时的事务日志备份是一个问题。
或者也许在检查站期间卡盘确实发生了减速?
不:
英特尔至强金牌四核 6142。
人们假设查询执行计划必须在“快”和“慢”之间有所不同。他们不是。
我们可以从检查中立即看到这一点。
我们知道更长的问题持续时间不是因为“糟糕”的执行计划:
因为如果读取的增加或 CPU 的增加是查询持续时间增加的原因,那么我们在上面已经看到了。没有相关性。
但是让我们尝试将持续时间与 CPU 读取区域产品指标相关联:
相关性变得更小——这是一个悖论。
编辑:更新散点图以解决 Excel 散点图中具有大量值的错误。
我接下来的步骤是让某人必须为被阻止的查询生成事件- 5 秒后:
EXEC sp_configure 'blocked process threshold', '5';
RECONFIGURE
Run Code Online (Sandbox Code Playgroud)
它不会解释查询是否被阻止了4秒。但也许任何阻止查询 5 秒的东西也会阻止一些 4 秒。
这是正在执行的两个存储过程的慢速计划:
相同的存储过程,具有相同的参数,背靠背运行:
| Duration (us) | CPU time (us) | Logical reads | Physical reads |
|---------------|---------------|---------------|----------------|
| 13,984,446 | 47,000 | 5,110 | 771 |
| 4,603,566 | 47,000 | 5,126 | 740 |
Run Code Online (Sandbox Code Playgroud)
呼叫 1:
|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
|--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
| |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
| | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
| | | |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
| | |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
| |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]), WHERE:([Contos
|--Filter(WHERE:([Expr1009]>(1)))
|--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
|--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
|--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC
Run Code Online (Sandbox Code Playgroud)
呼叫 2
|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
|--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
| |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
| | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
| | | | |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
| | | |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
| | |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
| |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]), WHERE:([Contos
|--Filter(WHERE:([Expr1009]>(1)))
|--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
|--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
|--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC
Run Code Online (Sandbox Code Playgroud)
计划相同是有道理的;它使用相同的参数执行相同的存储过程。
小智 2
查看 wait_stats,它将显示 SQL 服务器上最大的瓶颈是什么。
我最近遇到一个问题,外部应用程序间歇性缓慢。不过,在服务器本身上运行存储过程总是很快。
性能监控表明,服务器上的 SQL 缓存或 RAM 使用情况和 IO 根本不需要担心。
有助于缩小调查范围的是查询 SQL 收集的等待统计信息sys.dm_os_wait_stats
SQLSkills 网站上的优秀脚本将向您展示您最常遇到的脚本。然后您可以缩小搜索范围以确定原因。
一旦您知道什么等待是大问题,此脚本将帮助缩小正在经历等待的会话/数据库的范围:
SELECT OSW.session_id,
OSW.wait_duration_ms,
OSW.wait_type,
DB_NAME(EXR.database_id) AS DatabaseName
FROM sys.dm_os_waiting_tasks OSW
INNER JOIN sys.dm_exec_sessions EXS ON OSW.session_id = EXS.session_id
INNER JOIN sys.dm_exec_requests EXR ON EXR.session_id = OSW.session_id
OPTION(Recompile);
Run Code Online (Sandbox Code Playgroud)
上述查询和进一步的详细信息来自MSSQLTips 网站。
sp_BlitzFirst
Brent Ozar网站上的脚本也会向您显示导致速度变慢的原因。