SQL 大数据量查询调优案例

1次阅读

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

SQL 大数据量查询调优案例

WHERE 条件没走索引,查 100 万行变全表扫描

查得慢,八成是 EXPLAIN 看出没走索引。常见原因不是没建索引,而是条件用了函数或隐式转换——比如 WHERE DATE(create_time) = '2024-01-01'create_time 字段再有索引也白搭。

实操建议:

  • 把函数挪到右边:WHERE create_time >= '2024-01-01' AND create_time
  • 检查字段类型和参数类型是否一致:user_idBIGINT,但传了字符串 '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 多张大表时执行计划崩了

三张百万级表 JOINEXPLAIN 显示 type=ALL,驱动表选错,中间结果集爆炸。不是 SQL 写得不对,是优化器误判了行数。

实操建议:

  • ONWHERE 中的关联字段都建索引,尤其被驱动表的连接字段必须有索引
  • 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,比调参数管用十倍。但要注意:有些字段加了索引反而拖慢写入,得看读写比例。

text=ZqhQzanResources