说真的,搞数据库的谁没被慢查询折磨过?我见过最夸张的一次,一个简单的用户列表页,加载等了快半分钟,老板直接站在我背后盯着屏幕叹气。那种感觉,就像你开着老爷车上高速,油门踩到底,旁边的自行车都被超了。MySQL 查询慢,说白了就是两个原因:要么 SQL 写得太糙,要么数据库配置根本没调好。今天咱们不聊高大上的理论,就聊五个实打实的优化技巧,都是我在项目里摔过跟头后总结出来的,保证你上手就能用。

先说第一个技巧:给查询建索引,但别乱建。很多人一听索引能提速,就给每个字段都加上,结果写操作反而慢了,磁盘空间也蹭蹭涨。索引得用在刀刃上。你想想,平时查询最多的 WHERE 条件、JOIN 关联字段、ORDER BY 排序字段,这些才是索引的“菜”。比如你查询用户表,常按 和 筛选,那就在这两个字段上建个联合索引,顺序也有讲究——区分度高的放前面。我见过一个案例,原来查 100 万行数据要 5 秒,加了联合索引后直接降到 0.02 秒,老板当场给我加了鸡腿。但记住,索引不是越多越好,更新频繁的字段少建,否则每次插入都要重建树,得不偿失。
第二个技巧,别让 SELECT 毁了你。我见过太多人写 SQL 时图省事,直接 。你以为只拿一条数据,实际上 MySQL 仍然要把整行所有字段读出来,哪怕你只需要用户名。这就像你去超市买瓶饮料,结果售货员把整个货架搬过来让你挑。改写成 ,只拿需要的字段,不仅减少网络传输,还能利用覆盖索引——如果索引里恰好包含这些字段,MySQL 甚至不需要回表,直接从索引树读完事。我做过测试,同样查 10 万条数据,SELECT * 用了 3.2 秒,指定字段只要 0.8 秒,差距四倍。写 SQL 时多敲几个字段名,成本几乎为零,收益却肉眼可见。
第三个技巧,学会用 EXPLAIN 给查询做体检。很多人查询慢了就盲目猜测,要么加索引要么改 SQL,跟盲人摸象一样。其实 MySQL 自带一个叫 EXPLAIN 的工具,只要在 SQL 前面加上 EXPLAIN,它就会告诉你查询是怎么执行的:用了哪个索引、扫描了多少行、有没有做文件排序。比如你发现 列显示 ,那就是全表扫描,得赶紧加索引;如果 列显示 ,说明排序没走索引,需调整排序字段的索引顺序。我有个朋友,一个慢查询折腾了两天没搞定,我用 EXPLAIN 一看,发现他 JOIN 了两个大表,但关联字段没有索引,导致 MySQL 临时建了磁盘表来存中间结果。加了索引后,查询时间从 15 秒降到 0.1 秒。所以,别偷懒,每个慢查询都跑一次 EXPLAIN,比任何优化技巧都管用。
第四个技巧,分页查询别用 OFFSET 硬翻。很多人分页时习惯写 ,意思是跳过前面 100 条再取 10 条。但 MySQL 必须先扫描 100 条,然后丢掉前面的 90 条,只保留 10 条。这就像你去图书馆找第 10001 本书,管理员得从第一本一本数到 10001。数据量小还好,一旦到几十万页,查询直接崩。我优化过最狠的一个案例,分页到第 500 页时已经要 30 秒。解决方案是用主键或唯一索引做游标分页。比如用户按 ID 排序,下一页就查询 。这样每次只扫描 10 行,速度稳定在毫秒级。如果业务上必须跳页,可以先用覆盖索引查出主键,再关联回表,也比 OFFSET 快得多。记住,OFFSET 分页是性能杀手,能不用就别用。
第五个技巧,给 MySQL 喂点配置补药。有时候 SQL 写得再好,索引也建得完美,但服务器本身配置太差,照样慢。我见过一台跑 MySQL 的机器,内存只有 4 GB, 仍是默认的 128 MB。这样数据只能频繁从磁盘读取,速度自然慢。合理的做法是把 buffer pool 调到机器物理内存的 70% 左右,比如 16 GB 内存就给 12 GB。还有 ,这东西在 MySQL 8.0 已经废弃,但老版本仍在使用,且并发高时反而拖慢性能。慢查询日志一定要打开,,再设个 ,超过 2 秒的查询自动记录,方便定期排查。我有个客户,调完 buffer pool 和日志参数后,整体查询速度提升了 40%,再也不用凌晨三点爬起来查问题。
说了这么多,其实优化 MySQL 查询没那么玄乎。核心就三件事:SQL 写规矩点,索引建在要点上,配置别太寒酸。只要把这五个技巧逐个落实,大多数慢查询都能解决。但别忘了,优化是个持续过程,业务数据在涨,查询模式在变,今天快的查询,三个月后可能又慢了。所以养成习惯,每隔一段时间用 EXPLAIN 扫一遍核心查询,看看有没有新增的全表扫描,检查索引的使用率。实在遇到棘手的,也别硬扛,该上缓存就上缓存,该分库分表就分库分表。毕竟,让数据库飞起来,最终是为了让你能准时下班,对吧?


