【问题标题】:What is the proper way to run a long query against an active database?对活动数据库运行长查询的正确方法是什么?
【发布时间】:2014-10-03 14:52:58
【问题描述】:

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

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

所以我的问题有两个:

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

  2. 1234563事务开始 100% 超时?

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

【问题讨论】:

  • 这个视图是否碰巧加入了另一个视图?
  • 你看过底层查询的执行计划吗?
  • @HLGEM - 不,只是表,但来自同一服务器上的两个数据库。
  • @JiggsJedi - 不,但我将研究如何做到这一点。不知道这将如何解释不同的行为。
  • 获取执行计划,并向我们展示查询——也许我们可以提供一些建议。但是在数据库中,随着时间的推移,统计信息会变得“陈旧”,并导致性能下降,未正确转换/处理的变量会影响它,索引列中的空值可能会导致它。

标签: sql-server tsql command-timeout


【解决方案1】:

READ_COMMITTED 事务隔离级别中SELECT 查询的默认行为是在查询执行期间获取共享锁以提供请求的数据一致性(仅读取提交的数据)。这些锁通常是行级的,并在读取每一行后立即在查询执行期间快速释放。页面和表级别的意图锁定也较少,可防止在读取数据时对其进行并发更新。根据执行计划的具体情况,甚至可能在查询期间在表级别持有共享锁,这将阻止在查询执行期间对表进行更新,并导致读取器阻塞写入器。

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

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

【讨论】:

    【解决方案2】:

    实际上,我决定在每个月初创建一个快照,以便生成报告。然后在不再需要报告时删除。这似乎工作正常。我可以对数据库还原做类似的事情,但工作量会稍微多一些。这使得不需要第二个 SQL EE 许可证,并且允许我运行报告而无需锁定实时事务的表。

    【讨论】:

    • 如果您希望避免长时间运行的 select 查询阻塞其他查询,请考虑打开 READ_COMMITTED_SNAPSHOT 数据库选项,以便使用行版本控制而不是锁定来实现读取一致性。
    • @Dan - 谢谢。我认为查询都做了共享锁。我担心阻止短事务多表更新,因为这些更新是超时的。我将研究是否可以在类似于拍摄整个快照的场景中使用该选项。如果确实如此,并且您想提出解决方案,我会这样标记。真的,我只是想找到在执行活动事务更新的数据库上运行长报告的最佳实践。
    • 我将继续发布一个答案,其中包含有关读取 READ_COMMITTED_SNAPSHOT 选项的更多详细信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多