糟糕的 SQL 读取性能(罪魁祸首更新统计数据?)

Posted

技术标签:

【中文标题】糟糕的 SQL 读取性能(罪魁祸首更新统计数据?)【英文标题】:Terrible SQL reads performance (culprit update stats?) 【发布时间】:2011-04-19 20:03:37 【问题描述】:

我在 SQL Server 2008 R2 上运行并尝试微调性能。我尽我所能:

SQL 代码的代码审查 创建或删除我认为合适的索引 自动创建统计信息开启 自动更新统计信息开启 自动更新统计信息异步开启

我有一个持续存储数据的 24/7 系统。有时我们会阅读,这就是问题所在。有时读取需要几秒钟或更短的时间(这对我们来说是可以预期和可以接受的)。其他时候,读取需要几秒钟,可能需要一分钟才能完成存储过程,然后我们在 UI 上呈现数据。

如果我们再次读取,它会更快。 SQL 探查器将跟踪需要几秒钟的特定存储过程或查询。我们会放大该存储过程,并尽我们所能优化它。

我还跟踪了自动统计事件和重新编译事件。很难判断是否正在更新统计信息导致读取需要很长时间,或者是否重新编译导致它。有时,我看到分析器跟踪读取查询的重新编译,这花费了几分钟不可接受的时间,其他时候它不跟踪重新编译。

我试图阻止查询优化器阻止读取,直到它使用选项使用计划 XML 等重新编译或更新统计信息。但我遇到了编译错误,抱怨查询计划 XML 无效;这可能是真的,因为查询是安静的:涉及本地表变量的选择 + 连接。我有点破解了 XML,也许这就是它认为它无效的原因。所以我放弃了使用计划提示。

我们尝试了定期(每 15 分钟)手动运行更新统计信息,以尽可能使统计信息保持最新,但这会损害性能。 updatestats 阻止写入,我敢肯定甚至读取; updatestats 似乎维护了一堆统计数据,平均需要大约 80-90 秒。等待这么长时间的读取是不可接受的。

所以想法是让读取发生并防止重新编译/更新统计数据阻止它的情况,对吗?完全禁用自动统计是否有意义?或者在删除所有自动创建的统计信息后禁用自动创建统计信息?

这可能违反了 Microsoft 的建议,因为它们默认启用自动创建统计信息和自动更新统计信息,并且性能可能会受到影响,但您可以提供任何想法/提示将不胜感激。

【问题讨论】:

您提到“手动更新统计信息”,通过sp_updatestats?还是使用其他方法? 您是否检查过您的缓冲区缓存命中率或检查您的内存是否过于紧张? 架构的结构如何?大多数表都使用代理键吗?如果是这样,他们的类型是什么?即,大多数表是否使用标识列?指导?自然键?这些表有多大? 我不明白你在说什么问题是什么?您是说重新编译需要时间吗?那么“糟糕的 SQL 读取性能”是什么意思呢?读取次数高?或者它们需要很长时间,因为它们被阻止或需要从光盘中读取? @sOltan - Guid 作为键需要特别注意。您无法使用newid 生成您的 guid,否则读取性能将非常糟糕。您必须使用等效的 NewSeqentialGuid 或 COMB guid,它将部分 guid 替换为日期时间。这可能是您的性能问题的根源。 【参考方案1】:

从您的解释来看,以下(全部或部分)可能正在发生。

    您正在进行物理读取。避免这种情况的快速方法是增加你扔在盒子上的 RAM 量。您还没有提到服务器的硬件规格。请添加详细信息。 如果您跟踪 SQL 调用,那么您可以轻松找出 RECOMPILE 发生的原因。查看 EventSubClass 找出原因并努力解决。 参考:http://msdn.microsoft.com/en-us/library/ms187105.aspx 您提到了表变量。当不在正确的地方使用时,这些因会导致性能问题而臭名昭著。如果您在 JOIN 中使用表变量,则并行计划是不可能的,也没有统计信息。我不确定您使用的方式和位置,但尝试用临时表替换它们。从 SQL Server 2005 开始,您最多只能获得 STMT 重新编译,而不是像 2000 年那样获得完整的 SP 重新编译。 您提到了 Update Stats ASYNC 选项,这不会阻止查询。 此服务器上的 TOP WAIT STATS 是什么?您是否根据 CPU、逻辑读取和执行计数确定了昂贵的程序? 您是否使用虚拟文件统计信息 DMV 查看了页面预期寿命、IO 量? 每 15 分钟更新一次统计数据不是一个好计划。数据多久插入一次系统?您使用的采样率是多少?您的索引维护策略是什么? 您查看过缺失的索引 DMV 吗?

有很多很好的查询可以使用以下查询以更精细的方式识别问题。

参考:http://dl.dropbox.com/u/13748067/SQL%20Server%202008%20Diagnostic%20Information%20Queries%20%28April%202011%29.sql

还有很多其他的东西要看,但以上是一个很好的起点。

【讨论】:

Glenn Berry 的诊断信息查询链接非常棒。其中有很多有用的查询来帮助诊断性能问题。 嗨,请在帖子下方查看我的一些答案。 * 我查看了重新编译的原因,他们都说 2 - Statistics changed。 * 异步自动更新统计数据:这是一个好习惯吗? * 页面预期寿命大部分时间都在 500 以上,有时是 2000。 * 没有维护索引的策略。 * 会检查其他的东西【参考方案2】:

好的,这是我的恕我直言:

DBCC INDEXDEFRAG 值得一试,它是一个 ONLINE 函数,因此可以在实时系统上使用

您可能已达到架构设计的最大容量。您可以扩展这总是有帮助的,但您更有可能必须更改架构以牺牲简单性来实现更好的可扩展性

一个常见的技巧是partitioning。您正在写入一个表,其索引分布看起来与几个小时前完全不同——因此会降低性能。这是一个海量写入,这样的表可以分为每日写入和其余数据,每晚分批移动。

越来越多的人正在转换为CQRS。你可能是下一个。这通过将读取与写入分开来解决问题(一个非常简单的解释)。

【讨论】:

DBCC INDEXDEFRAG 是一个废弃的函数,被ALTER INDEX REBUILDALTER INDEX REORGANIZE 取代。 谢谢!我的 SQL Server 知识有点老了

以上是关于糟糕的 SQL 读取性能(罪魁祸首更新统计数据?)的主要内容,如果未能解决你的问题,请参考以下文章

CSS 性能问题

Windows四大傻X功能——那些拖慢系统性能的罪魁祸首

Entity Framework 4 中的 Linq 查询。糟糕的性能

使用jdbc操作时,如何提取数据的性能

检索 *** 的包元数据时出错

大型数组的 angular.copy 面临非常糟糕的性能