SQL Server Always On 次要副本上的查询执行时间更长

本文可帮助你解决在只读次要副本上遇到查询性能问题的问题。

原始产品版本:SQL Server
原始 KB 数: 4040549

现象

假设你有一个Microsoft SQL Server Always On 可用性组成员数据库,该数据库包含一 clustered row-store 个或多个具有索引的大型表。 一个或多个大型表的查询在主副本上完成的速度比次要副本更快。

说明

  • 该查询会导致对表的大部分部分进行聚集索引扫描。
  • 查询使用 NOLOCK 提示。
  • 对于快速和缓慢的执行,执行计划运算符和运算符顺序相同。
  • 查询 sys.dm_db_index_physical_stats 显示聚集索引的重大碎片。
  • 从 AlwaysOn 可用性组取消加入数据库可以提高相同(前)次要副本实例的性能,使其类似于主要副本的性能。

原因

强制实施快照隔离时, 将忽略 NOLOCK 提示。 主要副本和次要副本的执行持续时间差异发生的原因是 ,NOLOCK 提示在强制实施快照隔离的只读次要副本上被忽略,而不是在默认不强制实施快照隔离的主副本上。 这会导致对群集索引的扫描在次要副本上强制实施键顺序。 在主副本上, NOLOCK 提示优先,并影响行为。 当聚集索引高度碎片时,对只读辅助副本执行扫描的关键顺序会导致 SQL Server 发出单页读取。 但在主副本上,SQL Server 会执行分配单元扫描来读取每个 IO 请求的多个页面。

解决方法

若要解决此问题,请重新生成主副本上的索引。 然后,此操作将传播到次要副本。 有关详细信息,请参阅 有关使用 AlwaysOn 可用性组进行索引维护的建议。

详细信息

出现 SET STATISTICS IO 此问题时,执行计划的实际 I/O 统计信息信息可能有助于诊断。 这些内容提供有关读取页数的信息,但不包括读取页面的 IO 操作数。

相反,请首先查找聚集索引的碎片。 此外,当使用可用性组中的数据库运行查询时,可能会收集 性能监视器 IO 读取操作数/秒和 IO 读取字节数/秒进程计数器两次,并在从可用性组中删除数据库并联机时,再次从同一实例收集该数据库。 如果索引碎片导致次要副本上的单页读取,但不会导致主副本上的单页读取,则与数据库不在可用性组中时相比,会看到更多的读取 IO/秒和较小的读取字节数/秒。

此外,此行为可能发生,但并非在所有环境中明显显示。 例如,可以处理 IO/秒级别增加且延迟最少的 IO 子系统,类似的吞吐量可能会使此问题不受忽视。