游戏卡顿白皮书 › L12 数据库
执行计划变化导致查询变慢 Query plan regression (stats, parameter sniffing)
原因 ID db-plan-flip · 主责 运维团队·数据库运维 · 配合 研发团队·服务器开发
在含图示和实验的完整版中打开此卡片 →
代码没变,DB 却换了处理同一条查询的方式(执行计划),昨天 2 ms 的查询今天就变成几百 ms。
起因 统计信息自动更新、DB 重启、数据分布变化,让 DB 重新制定执行计划 → 结果 选中了不走索引的计划,同一条查询慢了几十到几百倍,连接被占住 → 画面表现 没有任何发布,某个功能的加载却突然变慢,其他请求也跟着等待
- 症状
- 操作延迟, 连不上/无限加载
- 因素
- 延迟, 停顿
- 谁会遇到
- 仅特定功能, 全服
- 何时出现
- 偶尔随机
- 负责方
- 主责 运维团队·数据库运维 · 配合 研发团队·服务器开发
- 研发团队要做的事
- 结果行数随参数值差异很大的查询,拆开写或考虑使用计划提示(hint),把查询设计成一定能走索引。
- 运维团队要做的事
- 监控慢查询和执行计划记录,固定好的计划(SQL Server 查询存储等),管理统计信息的更新时间。
- 监控图上
- 某一时刻起台阶式上升 · 各查询的平均执行时间
- 查看位置
- 定期收集同类查询的平均耗时,观察趋势。MySQL 看 events_statements_summary_by_digest 的 AVG_TIMER_WAIT,PostgreSQL 看 pg_stat_statements 的 mean_exec_time(12 及以下为 mean_time)。变慢前后的执行计划用 EXPLAIN 或 PostgreSQL 的 auto_explain 对比,SQL Server 用查询存储的“回归查询”(Regressed Queries)视图对比
- 确认依据
- 在没有发布的时间点,某条查询的平均耗时台阶式上升几十倍,该时间点与统计信息更新、DB 重启重合,执行计划也已改变
- 排除依据
- 执行计划没变却变慢,是数据量增长、锁等待或磁盘问题,锁等待看“热点行锁竞争”(db-hot-row)
- 确认手段
- 运维工具即可确认(无需游戏代码)
- 深入了解
- SQL Server 会复用按第一次传入的参数值制定的计划(参数嗅探)。按只有几件物品的新角色制定的计划,用在有几万件物品的老角色身上就会大幅变慢,反过来的情况也很常见。重启清掉计划后恢复正常,过后又会再次变差。
出处
- Query Processing Architecture Guide Microsoft SQL Server
参数嗅探:按编译、重新编译时传入的参数值制定执行计划 - Parameter Sensitive Plan Optimization Microsoft SQL Server
数据分布不均匀时,缓存的单个计划无法适合所有参数值 - Monitor performance by using the Query Store Microsoft SQL Server
统计信息、表结构、索引变化会让计划改变,计划缓存只保留最新的计划;用查询存储的强制计划固定好的计划,用“回归查询”(Regressed Queries)视图对比变慢的查询及其计划 - Statement Summary Tables MySQL
events_statements_summary_by_digest:按同类查询统计的 COUNT_STAR、AVG_TIMER_WAIT(平均耗时) - pg_stat_statements — track statistics of SQL planning and execution PostgreSQL
每条语句的 calls、total_exec_time、mean_exec_time(平均执行时间) - pg_stat_statements (PostgreSQL 12 Documentation) PostgreSQL
12 及以前的列名为 total_time、mean_time - auto_explain — log execution plans of slow queries PostgreSQL
把耗时超过 auto_explain.log_min_duration 的查询的执行计划记入日志
相关原因
同一层:L12 数据库
其他层中同样导致“操作延迟”的原因
查看含图示和实验的原卡片