可读辅助数据库查询存储

适用于: SQL Server 2025 (17.x) Azure SQL 数据库

查询存储适用于可读辅助副本,为在辅助副本上运行的工作负荷启用查询存储见解。 启用后,次要副本会将查询执行信息(如运行时和等待统计信息)流式传输到主副本,其中数据保存在查询存储中,并在所有副本中可见。

平台支持

目前,适用于可读辅助副本的查询存储功能已在 SQL Server 2025(17.x)和 Azure SQL 数据库中生产支持。 从 SQL Server 2025(17.x)开始,在 Azure SQL 数据库中,默认启用可读辅助数据库的查询存储。

在 SQL Server 2022(16.x)中,可读辅助数据库的查询存储将保持预览状态,因此在生产环境中不受支持,默认情况下处于禁用状态。 若要为 SQL Server 2022 (16.x)中的可读辅助副本启用查询存储,需要为主副本和所有可读辅助副本启用跟踪标志 12606。 跟踪标志 12606 不适用于基于 SQL Server 2022(16.x)的生产部署。 有关详细信息,请参阅 SQL Server 2022 发行说明。 对于 SQL Server 2025 (17.x),“Query Store” 功能在可读辅助数据库上默认启用

Azure SQL 数据库会自动注册并启用所有数据库,以支持查询存储以在 受支持的服务层级和高可用性方案中使用可读辅助数据库功能。 目前,Azure SQL 数据库超大规模不支持此功能。

目前,Azure SQL 托管实例或 Microsoft Fabric 中的 SQL 数据库不支持此功能。

支持的高可用性场景

  • 在 SQL Server 2025 (17.x) 实例上将查询存储用于可读辅助数据库之前,必须配置 AlwaysOn 可用性组

  • 对于 Azure SQL 数据库,可读辅助数据库的查询存储支持以下服务级别:

    • 使用活动异地复制的常规用途(没有内置的高可用性副本;需要辅助支持异地复制配置)
    • 高级版(包括内置高可用性副本;还支持活动异地复制)
    • 业务关键型(包括内置高可用性副本,支持活动异地复制)

为可读副本启用查询存储

如果查询存储尚未启用并在主副本上处于 READ_WRITE 模式,则必须在继续之前启用它。 对主副本上的每个所需数据库执行以下脚本:

ALTER DATABASE [Database_Name]
    SET QUERY_STORE = ON(OPERATION_MODE = READ_WRITE);

若要在所有可读辅助数据库上启用查询存储,请连接到主副本,并为要登记使用该功能的每个数据库执行以下脚本。

ALTER DATABASE [Database_Name]
    FOR SECONDARY
    SET QUERY_STORE = ON
    (OPERATION_MODE = READ_WRITE);

为次要副本启用自动计划更正

适用于:SQL Server 2022(16.x)及更高版本 Azure SQL 数据库。

为备份副本启用查询存储后,可以选择启用自动调优,以允许自动计划更正功能强制在备份副本上执行特定的计划。 这使查询优化器能够自动识别和修复辅助副本上执行计划回归导致的查询性能问题。

若要为次要副本启用自动计划更正,请连接到主副本并为每个所需数据库执行以下脚本:

ALTER DATABASE [Database_Name]
FOR SECONDARY
SET AUTOMATIC_TUNING (FORCE_LAST_GOOD_PLAN = ON);

禁用辅助副本的查询存储

若要在所有次要副本上禁用辅助副本的查询存储功能,请连接到 master 副本上的 primary 数据库,并为每个所需数据库执行以下脚本:

ALTER DATABASE [Database_Name]
    FOR SECONDARY
    SET QUERY_STORE = ON
    (OPERATION_MODE = READ_ONLY);

验证是否在辅助副本上启用了 Query Store

您可以通过连接到辅助副本上的数据库并执行以下 T-SQL 语句来验证是否在该辅助副本上启用了 secondary Query Store:

SELECT desired_state_desc,
       actual_state_desc,
       readonly_reason
FROM sys.database_query_store_options;

查询 sys.database_query_store_options 目录视图的结果应指示查询存储的实际状态为 READ_CAPTURE_SECONDARYreadonly_reason8

desired_state_desc actual_state_desc readonly_reason
READ_CAPTURE_SECONDARY READ_CAPTURE_SECONDARY 8

注解

术语

副本集定义为数据库的读/写副本(主副本)和一个或多个只读副本(辅助副本)被视为逻辑单元。 在这个上下文中,角色 是指特定副本的角色。 当一个副本在主角色中提供服务时,它是读/写副本,可以执行数据修改和读取操作。 当副本配置为仅执行只读活动时,它将充当辅助角色(辅助角色、地理辅助角色、异地高可用辅助角色)。 角色可以通过计划内或计划外故障转移事件进行更改,发生这种情况时,主要角色可能会成为辅助角色,反之亦然。

当前支持的角色包括:

  • 主要
  • 次要
  • 地理辅助数据库
  • 地理高可用性次级系统
  • 命名副本

工作原理

可以基于角色分析存储有关查询的数据作为工作负荷。 用于可读次要副本的查询存储使您能够监视任何可能在次要副本上执行的唯一只读工作负载的性能。 数据在角色级别聚合。 例如,SQL Server 分布式可用性组 配置可能包括:

  • 一个主要复制品,属于可用性组 1 (AG1) 的一部分

  • 两个本地次要副本,也是 AG1 的一部分

  • 另一个远程位置中的一个主要副本属于单独的可用性组(AG2)。 在 SQL Server 术语中,它通常被称为全局转发器。然而,对于可读辅助副本功能来说,查询存储将识别并引用它为 Geo secondary 副本,前提是它是一个地理分布的次要副本。

如果将 AG1 和 AG2 配置为允许只读连接,则当只读工作负荷针对 AG1 的任一辅助副本执行时,查询存储执行统计信息将发送到 AG1 的主副本并聚合并持久保存为从 secondary 该角色生成的数据,然后再将数据发送回 AG2 中的所有次要副本,包括 AG2 中的全局转发器。 当针对 AG2 的主副本执行单独的工作负荷时,全球转发器会将数据发送回 AG1 的主副本,并作为 Geo secondary 角色生成的数据予以持久保存。

从可观察性的角度来看,扩展了sys.query_store_runtime_stats 系统目录视图,以帮助识别执行统计信息的源角色。 此视图与 sys.query_store_replicas 系统目录视图之间存在关系,该视图可以提供更友好的角色名称。 在 SQL Server 中,列 replica_nameNULL. 但是,如果存在命名副本且用于只读工作负荷时,“Hyperscale”服务层的该列 replica_name 会被填充。

T-SQL 查询的一个示例,该查询可用于提供过去 8 小时内前 50 个查询的总体分析,消耗所有副本的 CPU 资源将是:

-- Top 50 queries by CPU across all replicas in the last 8 hours
DECLARE @hours AS INT = 8;

SELECT TOP 50 qsq.query_id,
              qsp.plan_id,
              CASE qrs.replica_group_id WHEN 1 THEN 'PRIMARY' WHEN 2 THEN 'SECONDARY' WHEN 3 THEN 'GEO SECONDARY' WHEN 4 THEN 'GEO HA SECONDARY' ELSE CONCAT('NAMED REPLICA_', qrs.replica_group_id) END AS replica_type,
              qsq.query_hash,
              qsp.query_plan_hash,
              SUM(qrs.count_executions) AS sum_executions,
              SUM(qrs.count_executions * qrs.avg_logical_io_reads) AS total_logical_reads,
              SUM(qrs.count_executions * qrs.avg_cpu_time / 1000.0) AS total_cpu_ms,
              AVG(qrs.avg_logical_io_reads) AS avg_logical_io_reads,
              AVG(qrs.avg_cpu_time / 1000.0) AS avg_cpu_ms,
              ROUND(TRY_CAST (SUM(qrs.avg_duration * qrs.count_executions) AS FLOAT) / NULLIF (SUM(qrs.count_executions), 0) * 0.001, 2) AS avg_duration_ms,
              COUNT(DISTINCT qsp.plan_id) AS number_of_distinct_plans,
              qsqt.query_sql_text
FROM sys.query_store_runtime_stats_interval AS qsrsi
     INNER JOIN sys.query_store_runtime_stats AS qrs
         ON qrs.runtime_stats_interval_id = qsrsi.runtime_stats_interval_id
     INNER JOIN sys.query_store_plan AS qsp
         ON qsp.plan_id = qrs.plan_id
     INNER JOIN sys.query_store_query AS qsq
         ON qsq.query_id = qsp.query_id
     INNER JOIN sys.query_store_query_text AS qsqt
         ON qsq.query_text_id = qsqt.query_text_id
WHERE qsrsi.start_time >= DATEADD(HOUR, -@hours, GETUTCDATE())
GROUP BY qsq.query_id, qsq.query_hash, qsp.query_plan_hash, qsp.plan_id, qrs.replica_group_id, qsqt.query_sql_text
ORDER BY SUM(qrs.count_executions * qrs.avg_cpu_time / 1000.0) DESC, AVG(qrs.avg_cpu_time / 1000.0) DESC;

SQL Server Management Studio (SSMS) 21 及更高版本中的查询存储报表提供副本下拉列表,该下拉列表提供跨各种副本集/角色查看查询存储数据的方法。 此外,当连接到可读次要副本时,对象资源管理器视图中的查询存储节点将反映查询存储的当前状态(即,READ_CAPTURE_SECONDARY)。

Azure SQL 数据库中可读辅助数据库遥测数据的查询存储

适用于:Azure SQL 数据库

通过 Azure 诊断设置传输查询存储 运行时统计信息 时,将包含两列以帮助标识遥测数据的副本源:

  • is_primary_b:一个布尔值,该值指示数据源自主副本(true)还是次要副本(false)
  • replica_group_id:对应于副本角色的整数

在跨副本集分析工作负载时,这些列对于澄清指标和性能数据至关重要。 配置诊断设置以将查询存储运行时统计信息流式传输到 Log Analytics、事件中心或 Azure 存储时,请确保在查询和仪表板中考虑这些列数据,以便按副本角色正确地细分数据。 有关配置诊断设置和可用指标的详细信息,请参阅 Azure Monitor 中的诊断设置

重要

Azure SQL 数据库的 Query Performance Insight(QPI)does not目前支持这一replica_group_id概念。 仪表板中显示的数据将汇总所有副本的运行时和等待统计数据。

可读次级副本的查询存储性能注意事项

辅助副本用于将查询信息发送回主副本的通道是用于使辅助副本保持最新状态的同一通道。 channel这里意味着什么?

在可用性组(HADR)配置中,副本使用专用传输层相互同步,该传输层承载主副本和辅助副本之间的日志块、确认和状态消息。 这可确保数据一致性和故障转移就绪性。

启用可读辅助数据库的查询存储时,它不会创建单独的网络端点。 而是在现有传输层上建立新的逻辑通信路径:

  • 对于 Azure SQL 数据库(非超大规模)、Azure SQL 托管实例和 SQL Server,这使用高可用性和灾难恢复 (HADR) AlwaysOn 传输层。

  • 对于 Azure SQL 数据库“超大规模”,将使用一个名为远程 Blob I/O 传输层的不同传输层。 远程 Blob I/O 传输层是计算节点和日志服务/页服务器之间的通信通道。 远程 Blob I/O 传输层提供可靠的加密通道,用于移动日志记录和数据页。

此路径使用同一加密会话将查询存储执行数据(查询文本、计划、运行时/等待统计信息)与正常的日志记录流量一起复用。 该功能有自己的捕获队列和接收队列,您可以通过从任何副本视角查询 sys.database_query_store_internal_state 视图来查看这些队列。

SELECT pending_message_count,
       messaging_memory_used_mb
FROM sys.database_query_store_internal_state;

辅助数据库中的数据保存在主数据库上的同一查询存储表中,这可能会增加存储要求。 在负载过大的情况下,可能会在传输通道上观察到延迟或回压。 适用于主数据库上的查询存储的同一临时查询捕获限制也适用于辅助数据库。 有关管理查询存储大小和捕获策略的详细信息和指南,请参阅 在查询存储中保留最相关的数据

查询 ID/计划 ID 的负面可见性

负数 ID 表示在辅助实例上查询/计划的临时内存中的占位符,然后再持久化到主实例。

在查询存储数据从可读次要副本保存到主副本之前,可以在查询存储的本地内存中表示形式( MEMORYCLERK_QUERYDISKSTORE_HASHMAP)中为查询和计划分配临时标识符。 查询和计划 ID 可以显示为负数,并且是占位符,直到主副本分配具权威性的标识符,这会在查询存储确定查询满足配置的 捕获模式要求之后发生。 如果已设置 自定义捕获策略 ,可以通过查询 sys.database_query_store_options 系统目录视图来查看必须满足的要求。

SELECT query_capture_mode_desc,
       capture_policy_execution_count,
       capture_policy_total_compile_cpu_time_ms,
       capture_policy_total_execution_cpu_time_ms
FROM sys.database_query_store_options;

将查询指定为捕获后,可以持久保存其运行时/等待统计信息和计划,并将本地临时 ID 替换为正 ID。 这还允许你使用计划强制或提示功能。