中转系统MySQL慢查询导致接口超时,索引优化实战
当中转系统出现接口响应慢甚至超时,很多运维第一步会去看程序代码,但真正的问题可能出在数据库。
MySQL 慢查询会直接拖垮接口响应速度,尤其是中转类系统频繁读写关联表时。
本文从一个典型故障场景入手,演示如何通过开启慢查询日志、分析执行计划、补充合适索引,逐步解决中转系统 MySQL 慢查询问题,零基础用户也可以直接照做。
先确认接口超时是否由数据库慢查询引起
排查之前,先看接口超时是否和数据库有关。
登录中转系统服务器,执行下面的命令确认 MySQL 当前连接数和线程状态:
mysql -uroot -p -e "SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW PROCESSLIST;"
如果发现大量 Sending data、Copying to tmp table 状态的连接,且某个 SELECT 或 UPDATE 语句执行时间特别长,基本可以判定是慢查询拖慢了接口。
此时需要把慢查询日志打开,记录所有超过阈值的 SQL。
开启慢查询日志,让慢 SQL 浮出水面
临时开启慢查询日志可以直接在 MySQL 命令行执行:
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = ON;
建议同时修改 my.cnf 让配置永久生效:
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
保存后重启 MySQL,或者用 SET PERSIST 使参数立即生效。
接着用 mysqldumpslow 查看慢查询日志里最耗时的几条 SQL:
mysqldumpslow -s at -t 10 /var/log/mysql/mysql-slow.log
一般能直接看到类似 SELECT * FROM order_info WHERE user_id=? 这样的语句,且执行时间经常超过 2 秒,这就是需要优化的目标。
AND status=?
ORDER BY create_time DESC
用 EXPLAIN 分析慢 SQL,找出索引问题
找到慢 SQL 后,在 SELECT 前面加上 EXPLAIN 看执行计划:
EXPLAIN SELECT * FROM order_info WHERE user_id = 12345 AND status = 1 ORDER BY create_time DESC;
重点看 type 和 key 两列。
如果 type 是 ALL,说明发生了全表扫描;
如果 key 是 NULL,说明没有使用任何索引。
对于中转系统里常见的用户维度查询,通常需要建立联合索引。
例如上面的 SQL,可以这样建索引:
ALTER TABLE order_info ADD INDEX idx_user_status_time (user_id, status, create_time);
索引顺序按等值条件在前、排序字段在后的原则放置。
这样既能过滤 user_id 和 status,也能让 ORDER BY create_time 直接走索引,避免文件排序。
创建索引并验证优化效果
执行完 ALTER TABLE 后,再次运行 EXPLAIN,确认 type 变成了 ref 或 range,key 显示刚创建的索引名,同时 Extra 里不再出现 Using filesort。
然后回到业务侧,直接执行原 SQL 看耗时:
SELECT * FROM order_info WHERE user_id = 12345 AND status = 1 ORDER BY create_time DESC;
如果之前需要 2 秒,现在降到 50 毫秒以内,说明索引生效。
同时观察慢查询日志,一段时间内不再记录该 SQL,接口超时报警也会自动消失。
建议在业务低峰期完成索引变更,避免锁表影响中转系统正常服务。
索引不生效的常见坑
索引建了还是慢,常见原因有两个。
一个是隐式类型转换:例如 user_id 是 varchar,查询条件却写成了数字,MySQL 会放弃索引。
另一个是前导模糊查询:LIKE '%keyword%' 无法走索引,建议改成前缀匹配或使用全文索引。
另外,联合索引要遵循最左前缀原则,如果查询条件里跳过了第一列,索引也不会被使用。
遇到这类情况,先用 EXPLAIN 重新核对,再决定是调整 SQL 写法还是修改索引结构。
完成以上步骤后,中转系统的接口超时问题基本能解决。
如果业务数据量持续增长,建议定期用 mysqldumpslow 和 EXPLAIN 复查慢查询,同时把慢查询阈值设置成 1 秒,让潜在风险提前暴露。