给慢查询加索引之前,先回答两个问题:时间消耗在哪一步,新的索引能减少哪部分工作?一次请求变慢,可能来自扫描数据过多、排序、锁等待、连接池排队,也可能只是需要返回的数据本身太多。把所有问题都归结为“缺索引”,容易增加写入与存储成本,却没有改善真正的瓶颈。

RootGS 技术编辑 · 发布日期:2026 年 9 月 18 日 · 原创技术指南

一、先固定查询场景,避免比较不同问题

记录数据库版本、表结构、现有索引、脱敏后的 SQL、参数范围和返回行数,并注明发生时间与并发量。同一条查询在不同客户、日期范围和数据分布下,可能表现完全不同。开发环境只有几百行数据时的速度,不能代表生产环境的访问成本。

区分应用等待、数据库执行和结果传输。如果数据库几毫秒就返回,而接口仍等待数秒,应继续检查连接池、应用处理和外部依赖。若异常主要发生在批量写入时,应结合已有的锁等待与事务监控,而不是看到 CPU 不高就排除数据库问题。采集慢日志属于运行配置变更,还需要考虑敏感参数与日志增长。

把一次慢请求分为应用等待、数据库执行与结果传输三个观察阶段
图 1:把一次慢请求分为应用等待、数据库执行与结果传输三个观察阶段。RootGS 原创技术示意图,不代表实际监控数据。

二、先用普通 EXPLAIN 读取计划

以下示例以 MySQL 8.4 为参考,演示一类“按客户、状态筛选,按时间取最近记录”的只读查询。orders、字段和数值均为教学示例,不对应真实客户表。请在测试数据或获准的环境中使用与实际版本匹配的语法。

EXPLAIN
SELECT id, created_at, total
FROM orders
WHERE customer_id = 1001
  AND status = 'paid'
ORDER BY created_at DESC
LIMIT 20;

普通 EXPLAIN 用来观察优化器选择的访问路径,不等于已经测得真实执行时间。重点查看访问类型、选择的索引、估算扫描量以及额外操作,并把它们放回完整查询结构中解释。多表查询还要看连接顺序及每层访问代价;一个局部步骤看似便宜,重复执行很多次后仍可能成为主要开销。

计划中的估算行数不是实际返回行数,也不是毫秒数。出现 filesort 不应直接理解为“一定在磁盘排序”,出现全表扫描也不必立即判为错误:小表、低选择性的条件或需要读取大部分行的查询,扫描可能是合理选择。要判断其代价,仍需结合数据规模与代表性参数。

三、索引顺序应服务于查询模式

对上面的查询,可以把 (customer_id, status, created_at) 作为一个待验证的联合索引候选:先按客户和状态缩小范围,再评估是否能够利用时间顺序减少额外排序。它只是候选方案,不是适用于所有订单表的固定答案。字段基数、其他查询模式、排序方式和已有索引都会影响最终选择。

联合索引具有最左前缀的使用特点,不能把三列任意调换后期待相同效果。以客户筛选为主的接口,与跨所有客户按状态统计的任务,可能需要不同访问路径。也不要为了追求覆盖,把所有查询返回列都加入索引:更宽的索引会占用更多空间,并增加写入时需要维护的数据量。

联合索引按客户、状态、时间组织,候选顺序必须由实际查询验证
图 2:联合索引按客户、状态、时间组织,候选顺序必须由实际查询验证。RootGS 原创技术示意图,不代表实际监控数据。

四、估算与实测必须分开

如果需要比较估算与实际执行,可以在支持的版本和受控环境中考虑 EXPLAIN ANALYZE。它会实际运行语句,不能因为名字里有 EXPLAIN 就当作没有执行成本;本文不建议直接对未知规模的生产查询运行它。先检查版本与语句支持范围,选择测试库或具有代表性数据的验证环境。

实际分析时关注各执行步骤的耗时、行数和循环次数,寻找估算与实际明显偏离的位置。不要把嵌套步骤的时间简单相加;也不要把某层单次耗时很小当作无关,因为它可能重复很多次。比较同一组参数、相近数据量和类似缓存条件,才有判断价值。

统计信息与数据分布变化可能影响计划选择。是否执行统计信息维护,应结合版本、存储引擎和维护窗口决定,不应看到估算误差就立即在繁忙主库执行操作。数据倾斜也意味着“一个样例变快”不足以说明所有客户都会变快。

五、上线前考虑写入、锁与回退成本

建立索引会消耗资源,具体的在线 DDL 能力、锁影响和临时空间需求,取决于版本、表结构及操作方式。发布计划应明确执行窗口、观察指标和中止条件,并关注复制延迟。不要笼统承诺“在线建索引完全不影响业务”。

上线前梳理候选索引是否与现有索引重叠,列出它要服务的关键查询,再使用代表性负载比较读写两端。删除旧索引也属于变更,不能只凭名称相似就删除。回退方案需要说明哪些应用版本依赖新索引、撤回是否同样耗时,以及出现问题时先控制哪一类负载。

索引变更需要同时验证读取收益、写入代价与不同参数的表现
图 3:索引变更需要同时验证读取收益、写入代价与不同参数的表现。RootGS 原创技术示意图,不代表实际监控数据。

六、验收标准是业务表现,而非计划里出现索引名

在一致的请求路径下比较查询耗时、接口高分位延迟、返回行数和错误率,同时关注写入延迟、数据库负载与存储增长。验证热门客户、小客户、宽时间范围和空结果等不同参数组合,避免只优化了一个演示样例。

如果读取更快但写入明显变慢,需要重新衡量收益;如果数据库执行已很短,而接口仍慢,应继续追踪应用链路。最终记录保留原始计划、候选方案、变更条件、验证数据与回退办法。索引是实现目标的手段,目标是让真实请求以可接受的资源成本稳定完成。

参考资料

此文章对您是否有帮助? 0 用户发现这个很有用 (0 投票)