索引选择稳定性需确保优化器在数据分布、统计更新或参数变化时持续选用高效执行计划;关键措施包括及时准确的统计信息更新、避免隐式转换与函数包裹、合理设计复合索引并INCLUDE非键列、定期监控执行计划告警。

索引选择稳定性,核心是让优化器在不同数据分布、统计信息更新或查询参数变化时,仍能持续选择高效执行计划,避免因“计划漂移”导致性能骤降。
统计信息及时且准确
优化器依赖统计信息估算行数,若过期或采样不足,易误判索引有效性。例如,大表插入百万新数据后未更新统计,优化器可能放弃本该走的高选择性索引,改走全表扫描。
- 对频繁增删的表,启用自动更新(如 SQL Server 的 AUTO_UPDATE_STATISTICS),并确认 AUTO_UPDATE_STATISTICS_ASYNC 为 OFF,避免估算滞后
- 对倾斜数据(如状态字段 95% 是 'done'),使用 FULLSCAN 或更高采样率(如 WITH SAMPLE 50 PERCENT)手动更新关键列统计
- 定期检查 sys.dm_db_stats_properties 中 last_updated 和 modification_counter,对变动超阈值的统计主动刷新
避免隐式类型转换与函数包裹
WHERE 子句中对索引列做函数操作或类型转换,会直接导致索引失效,优化器被迫回退到低效计划。
- 不要写 WHERE YEAR(order_date) = 2024,改用范围查询:WHERE order_date >= '2024-01-01' AND order_date 2025-01-01'
- 参数类型必须与列类型严格一致:@uid INT 对应 user_id INT;若列是 VARCHAR(50),传入 NVARCHAR 参数需显式 CAST 或确保应用层不带 N 前缀
- 避免在索引列上使用 LIKE '%abc'、IS NULL(除非是包含 NULL 的筛选且有对应索引设计)等无法利用 B-Tree 索引前缀的操作
控制参数嗅探与计划缓存污染
SQL Server 默认启用参数嗅探,首次执行时依据实际参数值生成计划并缓存。若首参极偏(如查热门ID),后续查冷门ID也复用该计划,引发性能抖动。
- 对参数敏感的查询,考虑加 OPTION (RECOMPILE)(适合低频、参数差异大场景)
- 用 OPTIMIZE FOR (@p = '典型值') 引导优化器按稳定分布生成计划
- 对 OLTP 高并发简单查询,可启用数据库级 ASSISTED_PLAN_GUIDE 或查询级别 USE PLAN 固定可靠计划(需测试验证)
索引设计匹配访问模式
索引不是越多越好,而是要覆盖高频查询的过滤、连接、排序和投影需求。缺失关键列会导致 Key Lookup 或 Sort 算子,放大 I/O 开销,间接诱发计划变更。
- 复合索引遵循“等值过滤 → 范围过滤 → 排序列”顺序,例如查询 WHERE status = 'active' AND created_at > '2024-01-01' ORDER BY score DESC,理想索引为 (status, created_at, score)
- 必要时添加 INCLUDE 列,把 SELECT 中的非键列包含进来,避免回表——特别是经常出现在 SELECT 列表但不参与 WHERE 的字段
- 定期用 sys.dm_exec_query_stats + sys.dm_exec_sql_text 找出逻辑读高、执行次数多的语句,结合其实际执行计划检查是否 Missing Index 或出现警告(如 “Index Spool”、“Convert Implicit”)










