别让慢查询拖垮你的应用
你有没有遇到过这样的情况:页面加载半天打不开,后台日志里全是超时告警?查来查去,问题出在一条 SQL 上。其实很多时候,这并不是数据库性能不行,而是索引没用好。
数据库索引就像书的目录,没有它就得一页页翻。但加了索引也不代表万事大吉,加得不对反而会拖慢写入、浪费存储。
先看执行计划,别瞎猜
很多人一觉得慢就想着加索引,结果越加越乱。正确的做法是先用 EXPLAIN 看执行计划。比如这条语句:
EXPLAIN SELECT * FROM users WHERE city = '北京' AND age > 25;如果结果显示 type 是 ALL,说明走了全表扫描,这时候才需要考虑加索引。
组合索引要讲究顺序
不是每个字段都单独建索引就好。比如上面那条查询,如果你分别给 city 和 age 建了单列索引,MySQL 很可能只用其中一个,另一个被忽略。
更高效的做法是建一个组合索引:
ALTER TABLE users ADD INDEX idx_city_age (city, age);注意顺序:等值查询字段放前面,范围查询放后面。因为索引是从左往右匹配的,city 是等值,age 是范围,这样能最大程度利用索引。
避免在索引列上做计算或函数操作
下面这种写法很常见:
SELECT * FROM orders WHERE YEAR(create_time) = 2024;看着没问题,但 YEAR() 函数会让索引失效。应该改成:
SELECT * FROM orders WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01';这样才能用上 create_time 的索引。
别忘了覆盖索引
有时候你只需要几个字段,比如查用户ID和姓名:
SELECT id, name FROM users WHERE city = '上海';如果有个索引包含这三个字段,比如 (city, name, id),数据库可能连数据行都不用回表,直接从索引里把数据拿出来,速度提升明显。
定期清理无用索引
开发过程中经常有人临时加索引测试,之后就忘了删。这些“僵尸索引”不仅占空间,还会影响写入性能。可以用工具如 pt-index-usage 分析哪些索引长期没被使用,果断下掉。
线上环境每张表的索引建议控制在5个以内,太多反而影响维护成本。
监控和迭代才是常态
业务在变,查询模式也在变。上周有效的索引,这周可能就成了瓶颈。把慢查询日志打开,设置阈值为1秒,定期看看有哪些SQL频繁出现,针对性优化。别指望一劳永逸。