可读辅助数据库持久化统计信息

适用于:适用于:sql Server 2025 (17.x) 在Microsoft Fabric 预览版中预览 Azure SQL 数据库 SQL 数据库

SQL Server 2022(16.x)中引入了Query Store for readable secondaries功能,用于可读辅助数据库的持久统计信息使用了Query Store在可读辅助数据库中搭建的基础架构。 SQL Server 2025 (17.x) 预览版默认 启用 可读辅助文件的查询存储,而在 SQL Server 2022(16.x)中,它 已关闭 ,并且需要跟踪标志 12606 才能启用。

SQL Server 2025(17.x)预览版及更高版本不再需要跟踪标志12606,如果使用,它将导致关闭查询存储的可读辅助数据库功能。

Background

在可读的次要副本上,当启用 自动创建统计信息 选项时,也可以自动创建统计信息,但这些统计信息是临时的,在重启实例时消失。 当只读数据库或只读快照的统计信息缺失或过时时,数据库引擎会在其中 tempdb创建和维护临时统计信息。

当数据库引擎创建临时统计信息时,统计信息名称将追加后缀 _readonly_database_statistic ,以区分临时统计信息与永久统计信息。 后缀 _readonly_database_statistic 保留为 SQL Server 生成的统计信息。 采用此方法的原因是解决针对可能要求主副本上不存在的不同统计信息的可读次要副本执行的工作负荷。

在次要副本上创建的临时统计信息仅对生成这些统计信息的副本可见。 主副本不会直接访问这些临时统计信息对象,并且仅在永久统计信息对象被持久化后才知晓它。 将临时统计信息保存到主副本时,它们将通过同步机制提供给可用性组中的所有副本。 持久性机制利用查询存储来支持在 SQL Server 2022(16.x)中引入的可读辅助数据库基础架构。 统计信息信息将发送到主副本,其中保留为永久统计信息,然后同步回所有次要副本。 此过程自动发生,无需手动干预。

支持目录视图

为了支持比较辅助和主要数据库之间的统计信息创建或更新,并帮助了解创建统计信息的位置,已将三个新列添加到 sys.stats 目录视图中:

列名称 数据类型 Description
replica_role_id tinyint 1 = 主节点、2 = 次节点、3 = 地理次节点、4 = 地理冗余次节点
replica_role_desc nvarchar(60) 主要、辅助、异地辅助数据库、异地 HA 辅助数据库
replica_name sysname 可用性组中的副本实例名称。 NULL 主副本

这些列在整个持久性生命周期中跟踪统计信息的所有权和来源。 当辅助副本创建临时统计信息并将其保存到主副本时,replica_role_id 和 replica_name 列标识源副本。 如果这些永久统计信息稍后在主副本上更新,则所有权会传输到主副本,这些统计信息反映在这些列中。

统计信息持久性特性

将临时统计信息从次要副本保存到主副本时,会发生几个重要行为:暂留后不会自动删除次要副本上的临时统计信息。 最初触发创建这些临时统计信息的查询将继续使用这些临时统计信息,直到查询重新编译或副本重启为止。 这意味着同一统计信息的临时版本和永久版本可以暂时共存。

优化器在确定是否使用统计信息时不考虑副本所有权。 它基于列覆盖率和选择性估计评估所有可用统计信息。 副本信息主要用于跟踪和故障排除。

当从临时统计信息创建的永久统计信息过时时,会出现一个值得注意的情况。 如果在这些统计数据的主要影响列上发生重大数据修改,则永久性统计数据可能会被视为过时。 当对次要副本的查询引用这些列时,次要副本会根据其对数据的视图更新统计信息,从而反映已通过重做过程进行的修改。

简言之,持久性不会删除辅助数据库刷新过时统计信息的能力;它只是添加一种机制来 跨副本共享 统计信息。

Observability

扩展事件

persisted_stats_operation(操作通道)针对enqueueddequeuedprocessedfailed事件引发。 这可以用于监测统计消息是否无法保存到主数据库上,或者是否有人有兴趣观察消息处理设施的工作状态。 当后台进程在主要副本和次要副本之间出现通信问题时,临时统计信息会保留在 tempdb 次要副本上,而后台进程会重试发送消息。

  • 9131:功能在 SQL 启动期间被禁用。
  • 9136:删除/修改表或索引。
  • 9137:自快照事务启动以来,模式已更改,请重试。
  • 9139:统计信息太大,无法发送到主数据库。

以下查询可以帮助了解表的统计数据,包括从次要副本保存的统计数据:

SELECT sch.[name] AS SchemaName,
       obj.[name] AS TableName,
       s.[name] AS StatsName,
       CASE WHEN s.stats_id >= 2 AND s.auto_created = 1 THEN 'AUTO_STATS'
           WHEN s.stats_id >= 2 AND s.auto_created = 0 THEN 'USER_CREATED_STATS'
           ELSE 'INDEX_STATS'
       END AS type,
       s.is_temporary,
       CASE WHEN s.replica_name IS NULL
                 AND s.replica_role_desc = 'PRIMARY'
                 AND s.stats_id >= 2
                 AND s.auto_created = 1 THEN 'PRIMARY' ELSE s.replica_name
       END AS replica_name,
       s.replica_role_id,
       s.replica_role_desc
FROM sys.schemas AS sch
     INNER JOIN sys.objects AS obj
         ON sch.schema_id = obj.schema_id
     INNER JOIN sys.stats AS s
         ON obj.object_id = s.object_id
WHERE sch.[name] <> 'sys'
ORDER BY sch.[name], obj.[name], s.stats_id;

注意事项

默认情况下会启用可读辅助数据库功能的持久统计信息,前提是启用自动创建统计信息选项,并且READABLE_SECONDARY_TEMPORARY_STATS_AUTO_CREATEREADABLE_SECONDARY_TEMPORARY_STATS_AUTO_UPDATE启用了数据库范围的配置选项,即默认配置。 没有数据库范围的设置来启用或禁用该功能。