如何优化数据库查询 实用操作步骤与避坑指南

从慢查询开始说起

你有没有遇到过这样的情况:用户点开一个页面,转圈等了五六秒才出来数据?后台日志一查,一条 SQL 执行了 4 秒。这种情况在数据量上来之后特别常见,尤其是订单、日志这类表,一个月下来几百万条记录,全靠 SELECT * 撑着,系统不卡才怪。

其实大多数性能问题,不是数据不行,而是查询写得太糙。它,不需要换硬件,也不用上分布式,先从最基础的改起。

给字段加索引,但别乱加

索引就像书的目录,没有它就得一页页翻。比如你要查某个用户的订单,WHERE user_id = 1001,如果 user_id 没有索引,数据库就得扫全表。数据一多,这代价就扛不住。

加个索引很简单:

CREATE INDEX idx_user_id ON orders (user_id);

但注意,索引不是越多越好。每加一个索引,写入数据时就要多维护一棵树,INSERT、UPDATE 变慢。特别是那些更新频繁又很少用来查询的字段,别盲目建索引。

避免 SELECT *

很多人写 SQL 图省事,直接 SELECT * FROM users。可你真需要所有字段吗?有时候只显示用户名和邮箱,却把加密密码、个人简介这些大字段也捞出来,浪费 I/O 和内存。

改成明确字段:

SELECT id, username, email FROM users WHERE status = 1;

既减少传输量,又可能走覆盖索引,效率提升明显。

合理使用 LIMIT

分页查数据时,别忘了加 LIMIT。曾经见过有人写后台列表,不加限制直接拉前一万条,页面卡死不说,数据库连接池都被占满。

哪怕前端暂时没做分页,后端也该设个保护值:

SELECT id, title FROM articles ORDER BY created_at DESC LIMIT 50;

要查更多?带上 offset 或者用游标分页,别一口气全拿。

拆解复杂查询

有些报表需求,动不动就是五六个表 JOIN,还套子查询。这种 SQL 看着厉害,执行起来特别容易走错执行计划,索引失效,临时表往磁盘一丢,速度直接掉底。

不如拆成几步,先查主数据,再用 IN 拿关联信息。虽然多几条语句,但每条都能走索引,总耗时反而更短。

利用缓存绕开查询

有些数据变化不频繁,比如商品分类、城市列表,每次都要查数据库纯属浪费。加一层 Redis 缓存,第一次查完存起来,后面直接读,响应从几百毫秒降到几毫秒。

缓存不是万能,得考虑一致性。但对读多写少的场景,效果立竿见影。

定期看慢查询日志

MySQL 开启 slow query log,把超过 1 秒的语句记下来。每周花半小时扫一眼,往往能发现被忽略的问题 SQL。可能是个没走索引的查询,也可能是个缺失的复合索引。

发现问题后,用 EXPLAIN 分析执行计划,看看是不是走了全表扫描,或者临时文件排序。

优化数据库查询,本质上是养成好习惯。别图一时方便写烂 SQL,等到系统撑不住再回头,代价更大。