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

时间:2011-04-19 20:03:37

标签: sql-server performance tsql

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

  • SQL代码的代码审查
  • 在我认为合适的情况下创建或删除索引
  • 自动创建统计信息
  • 自动更新统计信息
  • 自动更新统计信息async ON

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

如果我们再次阅读,那会更快。 SQL事件探查器将跟踪花费几秒钟的特定存储过程或查询。我们将放大该存储过程,并尽可能做我们可以做的一切来优化它。

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

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

我们尝试定期(每15分钟)手动运行更新统计信息,以尽可能多地保持统计信息的最新状态,但这会影响性能。 updatestats阻止写入,我确定甚至会读取; updatestats似乎保留了大量统计数据,平均需要大约80-90秒。等待那么久的阅读是不可接受的。

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

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

2 个答案:

答案 0 :(得分:8)

根据您的解释,看起来下面(全部或部分)可能正在发生。

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

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

    还有很多其他的事情要看,但上面是一个很好的起点。

答案 1 :(得分:1)

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

  • DBCC INDEXDEFRAG值得一试,是一个ONLINE函数,因此可用于实时系统

  • 您可以达到建筑设计的最大容量。您可以向上扩展,这可以始终有所帮助,但您更有可能更改架构以实现更好的可扩展性,从而牺牲简单性

  • 常见的伎俩是partitioning。您正在写一个表,其索引分布看起来与几个小时前不同 - 因此性能下降。这是一个大规模的写入,这样的表可以分为每日写入和其余的数据与夜间批次移动的东西。

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