对活动数据库运行长查询的正确方法是什么?

时间:2014-10-03 14:52:59

标签: sql-server tsql command-timeout

我们正在使用SQL Server 2012 EE,但目前没有在R / O镜像上运行查询的选项,虽然这是我的长期目标,但我担心在这种情况下我可能会遇到以下问题镜像也会更新我正在查询的数据。

我有一个视图,它连接来自两个数据库的多个表,并用于从现有数据开发票。其中三个表也通过持续交易积极更新。运行使用此视图的报告不是一个问题,但现在我们的数据库变得越来越大,我遇到了一些超时问题。首先查询超时,所以我将命令超时设置为0并重新启动查询,将所有4个CPU 100%挂起90分钟,然后我将其杀死。在此期间,活动交易没有问题。我查看了查询,发现我加入的一个字段没有编入索引,因此在该字段上创建了一个索引,重新编写报告,然后在三分钟内完成,所有CPU都忙,但根本没有挂断。两次查询相同的数据量。我觉得问题解决了。当然后来,我的老板运行了类似的查询,可能有更多的数据,但可能不是更多,我的实时交易在他的查询运行时开始超时100%。在那段时间里,我没有机会看到CPU的使用情况。

所以我的问题是两个:

  1. 鉴于我必须使用实时和活动数据库,运行长R / O查询的正确方法是什么,以便活动事务仍然可以继续?我正在考虑没有锁定,但我希望有一个更好的标准做法。

  2. 还有什么可能导致sqlserver挂出4个100%忙碌的CPU并且不会导致实时事务超时,但是当我的老板运行他的查询时,我添加了索引并且我的查询运行得更好,实时更新交易开始超时100%?

  3. 我知道这不是很多信息。我对sql profiling和性能监控不是很熟悉,但这种行为似乎很奇怪,我希望最佳实践是正确的解决方法。谢谢,戴夫

2 个答案:

答案 0 :(得分:1)

实际上我决定在每个月初创建一个快照来报告运行。然后在不再需要报告时删除。这似乎工作正常。我可以用数据库恢复做类似的事情,但稍微多一些工作。这允许不需要第二个SQL EE许可证,并允许我运行没有锁定表的报告以进行实时事务。

答案 1 :(得分:1)

SELECT事务隔离级别中READ_COMMITTED查询的默认行为是在查询执行期间获取共享锁以提供所请求的数据一致性(仅读取已提交的数据)。这些锁通常是行级的,并且在读取每一行之后立即在查询执行期间快速释放。页面和表级别的粒度意图锁也较少,因此在读取数据时会阻止对数据的并发更新。根据执行计划的细节,在查询期间甚至可能会在表级别保持共享锁,这将阻止在查询执行期间更新表,并导致读者阻止编写者。

设置READ_COMMITTED_SNAPSHOT数据库选项会导致SQL Server使用行版本控制而不是锁定来提供相同的读取一致性。在tempdb中维护行版本存储,以便在查询开始时查询请求的行发生更改时,将返回最新提交的行版本。此行版本控制行为可避免锁定,并在查询开始时有效地提供数据库的语句级快照。读者不会阻止作者和作者不阻止读者。不要将READ_COMMITTED_SNAPSHOT数据库选项与SNAPSHOT隔离级别混淆(常见错误)。

设置READ_COMMITTED_SNAPSHOT的缺点是额外的资源使用情况。启用数据库选项后,每行将额外增加14个字节的存储开销。更新和删除将在tempdb中生成行版本。这些版本在运行时间最长的查询期间需要tempdb空间,并且维护版本存储存在开销。还要考虑是否存在依赖于reader-block-writer锁定行为的现有应用程序。尽管存在这种开销,但并发优势可能会在提供读取完整性的同时根据您的工作负载产生更好的整体性能。有关详细信息,请参阅http://technet.microsoft.com/en-us/library/ms188277.aspx