Eri*_*ing 81 performance sql-server execution-plan parameter-sniffing query-performance
[敬礼]
(检查一个)
[ ] Well trained professional, [ ] Casual reader, [ ] Hapless wanderer,
Run Code Online (Sandbox Code Playgroud)
我有一个(检查所有适用的)
[ ] query [ ] stored procedure [ ] database thing maybe
Run Code Online (Sandbox Code Playgroud)
运行良好(如果适用)
[ ] yesterday [ ] in recent memory [ ] at some point
Run Code Online (Sandbox Code Playgroud)
但现在突然变慢了。
我已经检查过以确保它没有被阻止,并且它不是某些长时间运行的维护任务、报告或其他带外进程的受害者。
有什么问题,我应该怎么做,我可以提供哪些信息来获得帮助?
[*Insert appropriate closing remarks*]
Run Code Online (Sandbox Code Playgroud)
Eri*_*ing 92
亲爱的[你的名字]!
哦不,我很遗憾听到这个!让我们从一些基础知识开始,让您快速搞定。
这是一个解决诡异问题的出路。这个名字从舌头上滚下来。就像德语中的松鼠一样。
而且通常是你的朋友。
当查询访问您的服务器时,必须编译一个计划。为了稍后节省时间和资源,执行计划会根据参数将导致您的代码处理和返回的估计行进行缓存。
描述这种情况的最简单方法是想象一个存储过程,它需要从两个不平衡的群体中计算事物。
例如:
穿着 CrossFit 衬衫但没有受伤的人:零
穿着 CrossFit 衬衫但畏缩时畏缩的人:全部
显然,该代码的一次执行必须比另一次执行更多的工作,并且您想要执行完全不同的工作量的查询计划看起来完全不同。
这是一个真正难以找到、测试和修复的问题。
有时,您所需要的只是一点清晰度。或者更确切地说,您的计划缓存确实如此。
尝试运行EXEC sys.sp_recompile @objname = N'schema.procname'
。这将导致程序在下次运行时重新编译新计划。
这不会解决什么问题:
这不能保证什么:
您也可以指向sp_recompile
一个表或视图,但要预先警告所有涉及该表或视图的代码都将重新编译。这可能会使问题变得更加困难。
你的工作有点困难。您需要跟踪 SQL 句柄。您不想释放整个计划缓存——就像sp_recompile
对表或视图使用一样,您可能会触发(哈哈哈)一大堆意想不到的后果。
找出该命令的最简单方法是运行sp_BlitzWho *! 有一个名为“修复参数嗅探”的列,其中包含从缓存中删除单个计划的命令。但是,这与重新编译具有相同的缺点。
这不会解决什么问题:
这不能保证什么:
我们将需要以下东西:
如果查询正在运行,您可以使用sp_BlitzWho * 或sp_WhoIsActive来捕获当前正在执行的查询。
EXEC sp_BlitzWho;
EXEC sp_WhoIsActive @get_plans = 1;
Run Code Online (Sandbox Code Playgroud)
如果查询当前没有执行,您可以使用sp_BlitzCache *在计划缓存中检查它。
如果您使用的是 SQL Server 2016+,并且打开了查询存储,则可以使用sp_BlitzQueryStore *。
EXEC dbo.sp_BlitzCache @StoredProcName = 'Your Mom';
EXEC dbo.sp_BlitzQueryStore @StoredProcName = 'Your Mom';
Run Code Online (Sandbox Code Playgroud)
这些将帮助您跟踪存储过程的缓存版本。如果它只是参数化代码,那么您的搜索会更困难一些。不过,这可能会有所帮助:
EXEC dbo.sp_BlitzCache @QueryFilter = 'statement';
Run Code Online (Sandbox Code Playgroud)
您应该从其中任何一个中看到非常相似的输出。同样,邀请酷蓝色 clicky 列的查询计划是您的朋友。
共享计划的最简单方法是使用Paste The Plan *,或将 XML 转储到 pastebin 中。要做到这一点,请单击其中一个邀请的蓝色可点击列。您的查询计划应出现在新的 SSMS 选项卡中。
如果您对共享公司的代码和查询很敏感,您可以使用Sentry One 的免费计划资源管理器工具来匿名化您的计划。请记住,这使得获得帮助变得更加困难——匿名代码更难以阅读和理解。
我们谈到的所有这些工具都应该返回查询文本。您无需在此处执行任何其他操作。
获取参数有点困难。如果您使用的是Plan Explorer,则底部有一个选项卡为您列出所有这些。
如果您使用sp_BlitzCache *,则有一个可点击的列,它为您提供存储过程的执行语句。
您可以轻松地右键单击 SSMS 来编写脚本。
如果您想一次性获得所有内容,sp_BlitzIndex * 可以帮助您将其直接指向一张桌子。
EXEC dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow2010',
@SchemaName = 'dbo',
@TableName = 'Users';
Run Code Online (Sandbox Code Playgroud)
这将为您提供表定义(尽管不是创建语句),并为所有索引创建语句。
收集这些信息并将其添加到您的问题中应该能让人们获得足够的信息来提供帮助,或者为您指明正确的方向。
嗯,很酷。我为你感到高兴。你这个疯子。
人们认为他们“修复”参数嗅探的方式有很多:
但这些实际上只是以不同的方式禁用参数嗅探。这并不是说他们不能解决问题,他们只是没有真正找到根本原因。
那是因为找到根本原因通常有点困难。你必须寻找那些讨厌的“计划质量问题”。
从快速与慢速计划开始,寻找以下差异:
还要寻找使您的代码对参数嗅探敏感的不同运算符:
不要太沉迷于搜索与扫描、索引碎片化或任何人们对货物狂热的东西。
通常,有一个非常基本的索引问题。有时代码需要一些重写。
如果您想了解有关参数嗅探的更多信息:
应用程序慢,SSMS 快?- Erland Sommarskog
为什么要错误地调整存储过程(局部变量的问题) - Kendra Little
如何像专业人士一样使用参数并提高性能- Guy Glantser
参数嗅探、嵌入和重新编译选项- Paul White
如果您正在阅读本文,并且认为我错过了一个链接或有用的工具,请发表评论。我会尽力保持最新状态。
SQL*_*tor 30
参数嗅探并不是查询性能变化的唯一可能原因。以下任何常见原因都可能显示相同的症状:
此列表中的第 6 - 11 项只能在采取了一些明确的行动后才能发生。我猜您打算排除这些,但很多时候遇到挑战的人并不知道其他人进行了更改,在您开始清除计划缓存条目的路径之前,这值得检查。
小智 9
只是为了添加到现有答案中以防它们没有帮助,当您的查询在第二天“突然”出现不同时,请检查:
Reports ? Standard Reports ? Schema Changes History
。另一种可能性是,您的基础架构团队正在使用 VMware 上的 vMotion 等工具,并且支持您的 SQL 实例的虚拟机正在从主机无缝移动到主机,而 DBA 不知道。
当您的基础设施外包时,这是一个真正的问题......我真的做噩梦了。
归档时间: |
|
查看次数: |
37690 次 |
最近记录: |