郑州团队代码优化实践:数据库慢查询从8秒优化到200毫秒

2026-08-04 阅读 0 作者:500元建网站

问题发现

管城区百汇商贸的电商平台上线运行一个月后,运维监控开始频繁报警。阿里云的RDS监控显示,每天有200-300条慢查询(执行时间超过1秒的SQL),其中最慢的一条达到了8.2秒。客户那边反馈订单列表页面打开要等五六秒,有时候直接超时。

我们拿到了RDS的慢查询日志,按执行频率和耗时排序,发现top 5的慢查询集中在三个表上:订单表(orders,280万行)、订单明细表(order_items,860万行)、商品表(products,4.2万行)。数据库是MySQL 5.7,实例规格是4核8G。

第一刀:索引优化

最慢的那条8.2秒的SQL是订单列表查询,关联了orders、order_items、products三张表。我们用EXPLAIN分析了执行计划,发现order_items表的关联字段product_id没有索引,导致全表扫描。860万行的全表扫描,不慢才怪。

加了索引之后,这条SQL从8.2秒降到了1.5秒。但1.5秒还是不够快。继续看EXPLAIN,发现orders表的status字段也没有索引,而查询条件里WHERE status = 'paid'会过滤掉大量数据。加上status的联合索引(user_id, status, created_at)之后,降到了0.6秒。

索引优化这一步总共加了7个索引,慢查询从200多条降到了30条左右。但有几个索引加了之后写性能下降——订单表的INSERT操作从平均15ms涨到了45ms。这个取舍是可以接受的,因为读频率是写频率的10倍以上。如果写多读少就要慎重考虑了。

郑州科技市场旁边一家做O2O的公司之前也踩过这个坑,他们给每个WHERE条件字段都加了索引,结果写入性能直接崩了。索引不是越多越好,要看查询频率和写入频率的比例。

第二刀:SQL重写

索引加完之后还有30条慢查询,大部分是SQL写法的问题。最典型的是子查询:

优化前的SQL大概是这样:SELECT * FROM orders WHERE user_id IN (SELECT user_id FROM users WHERE register_date > '2024-01-01')。这个子查询在users表有120万行数据时,执行计划显示是DEPENDENT SUBQUERY,性能极差。

改成JOIN写法:SELECT o.* FROM orders o INNER JOIN users u ON o.user_id = u.user_id WHERE u.register_date > '2024-01-01'。改完之后从3.2秒降到了0.3秒。MySQL对JOIN的优化远好于子查询,这是常识但很多人写的时候不注意。

另一个常见问题是SELECT *。百汇的订单列表接口原来查的是SELECT * FROM orders,实际上前端只需要10个字段,但orders表有38个字段,其中有个content字段存的是订单备注,TEXT类型,单条数据最大可达64KB。改成只查需要的字段之后,数据传输量减少了70%,接口响应时间又快了100ms左右。

第三刀:分页方案调整

另外一个慢查询是深分页问题。百汇的后台管理系统有个订单查询页面,运营人员翻到第800页的时候,SQL变成LIMIT 16000, 20。MySQL处理深分页的方式是先查出前16020条数据,然后丢弃前16000条,效率极低。这个SQL执行时间4.5秒。

解决方案是"游标分页"(也叫延迟关联)。第一次查询只查主键ID:SELECT id FROM orders WHERE status = 'paid' ORDER BY created_at DESC LIMIT 16000, 20。这个查询走覆盖索引,不需要回表,速度快得多。拿到20个ID之后再用SELECT * FROM orders WHERE id IN (...)查详细数据。改完之后从4.5秒降到了180ms。

如果数据量更大,游标分页也不够用,可以考虑用"上一页另外一条记录的ID"作为分页起点,完全避免OFFSET。但这种方案有个限制:不能跳页,只能上一页下一页。对C端用户来说没问题,对后台管理系统需要跳页的场景就不合适了。百汇的运营人员说跳页功能可以不要,那就完美解决了。

优化结果与总结

三步优化做完,慢查询从每天200-300条降到了0-3条,核心接口的平均响应时间从2.8秒降到了180ms,P99从8秒降到了350ms。数据库CPU使用率从平均60%降到了20%。没有加硬件,纯靠代码和索引优化达到的效果。

这次优化最大的体会是:很多性能问题不是技术难度问题,而是意识和习惯问题。写SQL的时候多看一眼EXPLAIN、多想一下数据量级、少用SELECT *,能避免80%的慢查询。说白了,后端性能优化不是什么高深的技术活,就是把基本功做扎实。

电话咨询 微信咨询 在线咨询 返回顶部
xycx202108

微信扫码咨询

×