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分析查询在等待什么资源。
四、验证配置是否真正生效
配置完成后,不能只看“命令执行成功”,而要从三个层面验证:开关状态、参数值、以及是否真的有数据写入。
第一层,确认数据库级开关与操作模式:
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 后最容易踩的坑有三类。第一类是“启用了但没数据”,常见原因是 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_desc | READ_WRITE |
| 只读原因 | readonly_reason | 0 |
| 存储上限 | max_storage_size_mb | 按库容量规划,示例 2048 |
| 采集模式 | query_capture_mode_desc | AUTO 或 ALL |
| 数据写入 | sys.query_store_runtime_stats.last_execution_time | 持续更新 |