한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

游戏卡顿白皮书 › L12 数据库

缺少索引的查询 Missing index / full table scan

原因 ID db-no-index · 主责 研发团队·服务器开发 · 配合 运维团队·数据库运维

在含图示和实验的完整版中打开此卡片 →

没有索引时,要找到符合条件的行,就得把整张表读一遍(全表扫描)。

起因 发布新功能时加了一个没有索引的条件查询 → 结果 扫描全部几百万行,一条查询要几百 ms 到几秒 → 画面表现 邮箱、交易记录加载慢,连接被占住,其他请求也跟着等

症状
操作延迟, 连不上/无限加载
因素
延迟, 停顿
谁会遇到
仅特定功能, 全服
何时出现
做特定操作时
负责方
主责 研发团队·服务器开发 · 配合 运维团队·数据库运维
研发团队要做的事
新查询在发布前审查执行计划,补充索引,修改类语句(UPDATE、DELETE)也要确认走了索引。
运维团队要做的事
监控慢查询日志,找出全表扫描的查询并同步给研发团队,线上加索引采用锁持有时间短的在线方式。
数值参考
有索引时几 ms;没有索引时随数据量成比例变慢,大表上会慢几百到几万倍。
监控图上
某一时刻起台阶式上升 · DB 查询延迟、扫描行数
查看位置
MySQL 看 slow query log(开启 log_queries_not_using_indexes 后,未使用索引的查询也会记录)中的 Rows_examined、Rows_sent,以及 performance_schema events_statements_summary_by_digest 的 SUM_NO_INDEX_USED、SUM_ROWS_EXAMINED,再执行 EXPLAIN。PostgreSQL 看 pg_stat_user_tables 的 seq_scan、seq_tup_read,再执行 EXPLAIN
确认依据
发布后新出现的查询读取的行数(Rows_examined)比返回的行数(Rows_sent)多几千倍,EXPLAIN 显示全表扫描(MySQL type ALL,PostgreSQL Seq Scan)。大表的 seq_tup_read 从发布时间起陡增
排除依据
走了索引仍然慢,是锁等待或执行计划变化,看“热点行锁竞争”(db-hot-row)、“线上表结构变更(DDL)锁”(db-ddl-lock)、“执行计划变化导致查询变慢”(db-plan-flip)。小表的全表扫描可能是正常的
确认手段
运维工具即可确认(无需游戏代码)
深入了解
变慢的不只是读。不走索引的修改语句(UPDATE、DELETE)在某些 DB 上会把扫描过的行都锁住,连无关玩家的存盘也会被挡住。

出处

  1. How MySQL Uses Indexes MySQL
    没有索引时从第一行开始读完整张表,表越大开销越大
  2. Locks Set by Different SQL Statements in InnoDB MySQL
    没有合适的索引而全表扫描时,所有行都会被锁住,连其他用户的插入也被阻塞
  3. The Slow Query Log MySQL
    记录超过 long_query_time(默认 10 秒)的查询,也可以另外记录未使用索引的查询
  4. CREATE INDEX (PostgreSQL Documentation) PostgreSQL
    用 CONCURRENTLY 创建索引不会阻塞写入,普通创建会一直阻塞写入直到完成
  5. Statement Summary Tables MySQL
    events_statements_summary_by_digest:按同类查询统计的 SUM_NO_INDEX_USED(未使用索引执行的次数)、SUM_ROWS_EXAMINED
  6. EXPLAIN Output Format MySQL
    type 为 ALL 表示全表扫描,通常通过加索引避免
  7. The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
    pg_stat_user_tables 的 seq_scan(顺序扫描次数)、seq_tup_read(顺序扫描读取的行数)
  8. Using EXPLAIN (PostgreSQL Documentation) PostgreSQL
    Seq Scan:按顺序读取表中所有行的执行计划

相关原因

同一层:L12 数据库

其他层中同样导致“操作延迟”的原因

查看含图示和实验的原卡片