3. 启用与配置Query Store

Query Store 是 SQL Server 2016 及 Azure SQL 中引入的“查询性能飞行记录仪”,它以数据库为作用域,把编译计划、运行时统计和执行历史持久化到用户数据库内部的系统表中。要让这套机制真正发挥作用,第一步不是去查报表,而是把开关打开、把参数配好,并确认它确实在采集数据。本节围绕“启用—配置—验证”这条主线,讲清楚每一步到底改了什么、为什么这样改、以及如何判断配置是否生效。

一、启用前先确认前提条件

Query Store 是数据库级功能,启用前需要确认三件事。第一,数据库兼容级别必须为 130(SQL Server 2016)或更高;兼容级别低于 130 时,ALTER DATABASE ... SET QUERY_STORE = ON 会直接报错。第二,执行者需要具备 ALTER DATABASE 权限,通常由 db_owner 或更高角色完成。第三,要评估目标数据库的写入压力:Query Store 默认会持续写入计划与运行时统计,对高写入负载的库需要提前规划 MAX_STORAGE_SIZE_MB 与清理策略。

可以用下面这条语句快速检查兼容级别与当前 Query Store 状态:

SELECT name, compatibility_level, is_query_store_on
FROM sys.databases
WHERE name = 'SalesDB';

如果 compatibility_level 小于 130,先执行 ALTER DATABASE SalesDB SET COMPATIBILITY_LEVEL = 130;,再继续后续操作。

二、启用 Query Store 的最小语句

启用动作本身只有一行,但它的语义是“在数据库上打开 Query Store 并开始采集”:

ALTER DATABASE SalesDB SET QUERY_STORE = ON;

执行成功后,SQL Server 会为该数据库创建一组内部目录视图(如 sys.query_store_query、sys.query_store_plan、sys.query_store_runtime_stats),并开始按默认参数采集。默认参数在多数场景下可用,但在生产库中往往需要显式调整,尤其是存储上限、采集模式和清理策略。

三、用一条 ALTER DATABASE 完成参数配置

Query Store 的参数通过 ALTER DATABASE ... SET QUERY_STORE ( ... ) 一次性设置。下面给出一个面向生产库的示例配置,并逐项说明其含义:

ALTER DATABASE SalesDB
SET QUERY_STORE (
    OPERATION_MODE = READ_WRITE,
    MAX_STORAGE_SIZE_MB = 2048,
    INTERVAL_LENGTH_MINUTES = 15,
    STALE_QUERY_THRESHOLD_DAYS = 30,
    SIZE_BASED_CLEANUP_MODE = AUTO,
    QUERY_CAPTURE_MODE = AUTO,
    MAX_PLANS_PER_QUERY = 200,
    WAIT_STATS_CAPTURE_MODE = ON
);

各参数的作用如下:

  • OPERATION_MODE:READ_WRITE 表示正常采集;READ_ONLY 停止写入但保留历史数据,适合排障期间冻结现场;OFF 则关闭采集。
  • MAX_STORAGE_SIZE_MB:Query Store 在数据库内可占用的最大空间。达到上限后,若 SIZE_BASED_CLEANUP_MODE = AUTO,系统会自动清理最旧的数据;若为 OFF,则停止采集并进入只读状态。
  • INTERVAL_LENGTH_MINUTES:运行时统计的聚合时间窗口,默认 60 分钟。调小到 15 分钟可以更精细地观察短时性能抖动,但会增加行数与存储开销。
  • STALE_QUERY_THRESHOLD_DAYS:超过该天数未被执行的查询将被清理,默认 30 天。
  • SIZE_BASED_CLEANUP_MODE:AUTO 表示空间不足时自动清理;OFF 表示不自动清理,需人工干预。
  • QUERY_CAPTURE_MODE:ALL 采集所有查询;AUTO 忽略执行次数极少、编译开销极小的查询;NONE 停止采集新查询但保留已有数据。
  • MAX_PLANS_PER_QUERY:单个查询保留的最大计划数,默认 200,防止计划爆炸。
  • WAIT_STATS_CAPTURE_MODE:是否采集等待统计,开启后可以结合 sys.query_store_wait_stats 分析查询在等待什么资源。
如果数据库处于 Always On 可用性组中,Query Store 的配置会随数据库一起同步到辅助副本;但辅助副本默认不采集运行时统计,需要在只读副本上单独评估。

四、验证配置是否真正生效

配置完成后,不能只看“命令执行成功”,而要从三个层面验证:开关状态、参数值、以及是否真的有数据写入。

第一层,确认数据库级开关与操作模式:

SELECT actual_state_desc, readonly_reason,
       current_storage_size_mb, max_storage_size_mb
FROM sys.database_query_store_options;

期望看到 actual_state_desc = READ_WRITE,且 readonly_reason = 0。如果显示 READ_ONLY,需要结合 readonly_reason 判断原因,例如空间不足、数据库处于只读状态或兼容级别不满足。

第二层,核对参数是否与预期一致:

SELECT desired_state_desc, actual_state_desc,
       interval_length_minutes, stale_query_threshold_days,
       size_based_cleanup_mode_desc, query_capture_mode_desc,
       max_plans_per_query, wait_stats_capture_mode_desc
FROM sys.database_query_store_options;

第三层,确认数据确实在写入。执行几条业务查询后,检查运行时统计是否有新增行:

SELECT TOP 10
    q.query_id,
    p.plan_id,
    rs.count_executions,
    rs.avg_duration,
    rs.last_execution_time
FROM sys.query_store_runtime_stats AS rs
JOIN sys.query_store_plan AS p ON rs.plan_id = p.plan_id
JOIN sys.query_store_query AS q ON p.query_id = q.query_id
ORDER BY rs.last_execution_time DESC;

如果 last_execution_time 持续更新,说明采集链路正常。若长时间没有新行,需要检查 QUERY_CAPTURE_MODE 是否被设为 NONE,或数据库是否处于只读状态。

Query Store 启用与配置验证链路 ① 前提检查 兼容级别 ≥ 130 ALTER DATABASE 权限 ② 启用开关 SET QUERY_STORE = ON 创建内部目录视图 ③ 参数配置 存储/采集/清理 ALTER DATABASE SET ④ 验证生效 状态+参数+数据 关键参数与作用 OPERATION_MODE READ_WRITE / READ_ONLY / OFF MAX_STORAGE_SIZE_MB 存储上限,示例 2048 INTERVAL_LENGTH_MINUTES 统计聚合窗口,示例 15 STALE_QUERY_THRESHOLD_DAYS 过期清理天数,示例 30 QUERY_CAPTURE_MODE ALL / AUTO / NONE MAX_PLANS_PER_QUERY 单查询计划上限,示例 200 三层验证与判读 第一层:开关状态 sys.database_query_store_options 期望 actual_state_desc = READ_WRITE 第二层:参数核对 desired_state_desc 与 actual 一致 interval / capture_mode 符合预期 第三层:数据写入 sys.query_store_runtime_stats last_execution_time 持续更新 异常时回查参数

五、常见配置陷阱与处理建议

实际运维中,启用 Query Store 后最容易踩的坑有三类。第一类是“启用了但没数据”,常见原因是 QUERY_CAPTURE_MODE 被误设为 NONE,或者数据库处于 READ_ONLY 状态导致 readonly_reason 非零。第二类是“空间被吃满”,表现为 current_storage_size_mb 接近 max_storage_size_mb,此时应检查 SIZE_BASED_CLEANUP_MODE 是否为 AUTO,并考虑调大上限或缩短 STALE_QUERY_THRESHOLD_DAYS。第三类是“统计粒度太粗”,如果 INTERVAL_LENGTH_MINUTES 仍为默认 60,短时抖动会被平均掉,排障时容易误判。

修改 MAX_STORAGE_SIZE_MB 或 INTERVAL_LENGTH_MINUTES 不会清空已有数据,但会改变后续采集行为。生产环境调整前建议先在测试库验证对写入负载的影响。

六、一份可直接执行的配置检查清单

把上面的操作整理成可复用的检查项,便于在多个数据库上批量执行:

检查项执行语句/视图通过标准
兼容级别sys.databases.compatibility_level≥ 130
开关状态sys.database_query_store_options.actual_state_descREAD_WRITE
只读原因readonly_reason0
存储上限max_storage_size_mb按库容量规划,示例 2048
采集模式query_capture_mode_descAUTO 或 ALL
数据写入sys.query_store_runtime_stats.last_execution_time持续更新