写SQL一时爽,优化火葬场?实战避坑指南来了

2026-05-11 10 0

写SQL一时爽,优化火葬场?实战避坑指南来了

各位搞后端的朋友,一定都经历过这个场景:凌晨两点,线上报警响起,你揉着惺忪的眼睛打开监控,发现某个接口响应时间从200ms飙升到了8秒。登录数据库一查,好家伙,一条看似简单的查询跑了7秒多。再一看执行计划,哦豁,全表扫描。

这不是段子,这是每个后端工程师成长路上的必修课。今天咱们就来聊聊SQL优化那些事儿,不整虚的,全是实战干货。

一、索引不是万能药,别乱加

很多人遇到查询慢,第一反应就是加索引。加索引确实能解决问题,但乱加索引可能会带来更大的问题。

我之前遇到过一个场景,某个商品表有2000万数据,开发同学说查询慢,我一看执行计划,发现他建了7个索引,其中3个是复合索引。问题是这7个索引里,有4个几乎从来不用,还有一个复合索引的第一个字段区分度极低,加了等于没加。

索引不是越多越好,每多一个索引,INSERT/UPDATE/DELETE操作就要多维护一份。想象一下,你在一个仓库里放了10个不同的索引牌,每次货物进出都要更新所有牌,这不是自找麻烦吗?

那么怎么判断该不该加索引?

  • WHERE条件里的字段:频繁出现在WHERE、JOIN、ORDER BY里的字段,可以考虑加索引
  • 区分度要够高:一个字段如果90%的值都是一样的,加索引等于没加,因为数据库优化器大概率会直接走全表扫描
  • 复合索引要注意顺序:左边列必须用上,否则复合索引白建。比如建了(name, age, city)的索引,但查询只用了age和city,那这个索引用不上

二、EXPLAIN是你的好朋友,必须会用

很多同学写SQL从来不看执行计划,这就好比开车不看仪表盘——你都不知道油耗多少、发动机啥状态,怎么知道要不要优化?

这行命令能告诉你很多东西:

  • type:查询类型,从好到差依次是system > const > eq_ref > ref > range > index > ALL。全表扫描是ALL,是你要重点优化的
  • key:实际使用了哪个索引
  • rows:预计扫描多少行。这个数字越大,越需要优化
  • Extra: Using filesort、Using temporary 这些都是警告信号

我之前见过一个SQL,type是ALL,rows显示800万,Extra里写着Using filesort。这意味着数据库要扫描全表然后排序,数据量大了直接爆内存。这种就必须优化。

三、JOIN不是你想用就能用的

JOIN是SQL里的高级操作,但很多人用得特别随意,完全不看数据量和关联条件。

有一次我看到一条SQL,6张表JOIN在一起,每张表都是百万级数据。我问开发同学为什么这么设计,他说这样写很简洁,逻辑也清晰。我只能说,逻辑是清晰了,执行时间也清晰了——清晰地要跑20秒。

JOIN的本质是把多个表的数据按照条件拼接。数据量大了,JOIN的复杂度会指数级上升。6张表JOIN,不是6倍的慢,可能是6的阶乘那么慢。

优化JOIN的几个原则:

  • 小表驱动大表:让数据量小的表作为驱动表,先过滤再关联
  • 关联字段必须有索引:ON的条件字段如果没有索引,关联就是灾难
  • 控制结果集:关联前先把数据过滤到位,别指望数据库帮你智能筛选
  • 考虑分步查询:有时候拆成两条简单SQL比一条复杂JOIN快得多

四、分页优化是大坑,必须重视

LIMIT offset, size 这个语法相信大家都用过,但数据量大的时候,这个offset会要命。

假设你要查第1000页,每页20条。很多人的写法是:

这条SQL会先扫描前20020行,然后丢弃前20000行,只返回20行。扫描了2万多行,结果只用了20行,效率低得离谱。

正确的做法是使用基于索引的分页:

假设last_id是上一页最后一条记录的id,那这条SQL直接定位到20000的位置往后取20条,最多扫描20多行。这就是经典的游标分页思想。

五、慢查询日志是宝藏,要擅用

很多人不知道MySQL有慢查询日志,这个日志记录了所有超过指定时间的SQL,是优化的第一手资料。

配合mysqldumpslow工具,可以按执行次数、平均耗时等维度排序,找出真正的问题SQL:

这比你在监控里一条条找高效多了。慢查询日志里的SQL,是真正需要优化的SQL,比你拍脑袋猜要靠谱得多。

六、总结:优化是个系统工程

说了这么多,其实SQL优化的核心思想就三条:

  1. 减少扫描范围:让数据库少干活,能用索引用索引,能过滤先过滤
  2. 减少数据量:JOIN前先过滤,分页用游标,别一股脑全扫出来
  3. 让数据库知道你在干什么:加合适的索引,让优化器做出正确选择

最后说一句,写SQL和优化SQL是两码事。写SQL是实现功能,优化SQL是追求效率。一个合格的后端工程师不仅要能写出来,还要能让它跑得快。毕竟,用户等不耐烦的。

好了,今天的分享就到这里。如果你也有SQL优化的血泪史,欢迎留言交流。咱们下期再见!

相关文章

那次P99延迟暴涨,让我彻底重新理解了数据库连接池
告别祖传代码:后端重构的正确姿势
你以为加了索引就能飞?SQL优化路上的那些自我感动
API设计避坑指南:那些让前端想打人的操作
【AI探索】最近AI圈发生了什么?这些新鲜事我不允许你不知道!
AI编程工具横评:我让Copilot、Claude和GPT-4同时写代码,结果笑死我了

发布评论