where条件未走索引致慢查,主因是函数或隐式转换;应避免date()等函数作用于索引列,改用范围查询;分页慎用offset,建议用游标或缓存;索引需权衡读写比例。

WHERE 条件没走索引,查 100 万行变全表扫描
查得慢,八成是 EXPLAIN 看出没走索引。常见原因不是没建索引,而是条件用了函数或隐式转换——比如 WHERE DATE(create_time) = '2024-01-01',create_time 字段再有索引也白搭。
实操建议:
- 把函数挪到右边:
WHERE create_time >= '2024-01-01' AND create_time - 检查字段类型和参数类型是否一致:
user_id是BIGINT,但传了字符串'123',mysql 会隐式转,索引失效 - 用
EXPLAIN format=TREE(MySQL 8.0+)看真实执行路径,比老版EXPLAIN更准
ORDER BY + LIMIT 在大数据集上卡死
想取最新 10 条记录,写 select * FROM logs ORDER BY id DESC LIMIT 10,结果响应几秒甚至超时——因为 MySQL 先排序全部 500 万行,再取前 10 条。
实操建议:
- 加覆盖索引:
CREATE INDEX idx_id_status ON logs (id DESC, status),让排序直接走索引 - 如果只按时间查,别用
id排序:用created_at字段建倒序索引,并确保查询条件能过滤掉大部分数据 - 避免
SELECT *:只查需要的字段,减少回表和网络传输开销
JOIN 多张大表时执行计划崩了
三张百万级表 JOIN,EXPLAIN 显示 type=ALL,驱动表选错,中间结果集爆炸。不是 SQL 写得不对,是优化器误判了行数。
实操建议:
- 给
ON和WHERE中的关联字段都建索引,尤其被驱动表的连接字段必须有索引 - 用
STRAIGHT_JOIN强制指定驱动表顺序(MySQL),比如SELECT STRAIGHT_JOIN ... FROM small_table JOIN big_table ON ... - 检查统计信息是否过期:
ANALYZE TABLE orders;,旧统计会导致优化器选错执行计划
分页查第 10000 页,OFFSET 越大越慢
SELECT * FROM products ORDER BY id LIMIT 100000, 20 这种写法,MySQL 必须先跳过前 10 万行,IO 和 CPU 成倍涨。
实操建议:
- 改用游标分页:
WHERE id > 123456 ORDER BY id LIMIT 20,依赖有序主键或唯一时间戳 - 如果业务允许,加缓存层:把分页结果缓存为
page_1000这样的 key,避免反复查库 - 千万别在高并发场景下暴露
OFFSET参数给前端,容易被刷垮
真正卡住的往往不是语法,是索引设计和执行计划之间的错位。一个 EXPLAIN 加一行 ANALYZE TABLE,比调参数管用十倍。但要注意:有些字段加了索引反而拖慢写入,得看读写比例。