大表查询慢的核心在于数据量与访问模式不匹配索引、统计信息或执行计划;优化关键为减少I/O、精准路径,包括建覆盖索引、游标分页、分区归档、分析执行计划及精简查询。

大表查询慢,核心问题往往不在SQL写得“错”,而在于数据量和访问模式不匹配索引、统计信息或执行计划。优化不是堆硬件,而是让数据库用更少的I/O、更精准的路径拿到数据。
建对索引:别只盯WHERE,覆盖扫描才是关键
单列索引在多条件查询中容易失效;联合索引顺序不对,等于没建。重点看查询中高频出现的过滤字段+排序字段+SELECT返回字段:
- WHERE a = ? AND b > ? ORDER BY c → 推荐索引 (a, b, c)
- 如果还要 SELECT d, e,且d/e也在表中频繁读取,考虑把它们加到索引末尾 → (a, b, c, d, e),实现“索引覆盖”,避免回表
- 区分度低的字段(如 status=0/1)单独建索引意义小,但作为联合索引的后缀可能有用
控制数据访问范围:分页、分区、归档三步走
动辄千万级的表,全表扫描或深分页(OFFSET 1000000 LIMIT 20)会拖垮性能:
- 用游标分页替代 OFFSET:记录上一页最后一条的主键值,下一页查 WHERE id > last_id LIMIT 20
- 按时间/业务维度做范围分区(如按月 partition by range (created_at)),让查询自动命中子分区
- 冷热分离:把一年前的历史订单归档到历史表,主表只留活跃数据,DELETE前先评估是否真要删,有时逻辑标记 + 定期归档更安全
让执行计划说实话:别猜,要看
EXPLAIN 或 EXPLAIN ANALYZE 是唯一真实反馈。重点关注几项:
- type 字段:ALL(全表扫描)和 index(全索引扫描)要警惕;尽量看到 ref / range / const
- rows 估算行数:如果远大于实际返回结果,说明统计信息过期,及时 ANALYZE TABLE 表名
- Extra 列:出现 Using filesort 或 Using temporary,意味着排序/聚合没走索引,需调整字段顺序或加覆盖索引
精简查询本身:少查、少算、少联
应用层常犯的错误是“一次查全再筛选”,数据库却为此做了大量无用工作:
- SELECT * 改成明确字段列表,尤其避开大文本(TEXT/BLOB)字段
- 避免在 WHERE 或 ORDER BY 中对字段做函数操作,如 WHERE DATE(create_time) = '2024-01-01' → 改为 create_time >= '2024-01-01' AND create_time
- 多表 JOIN 前确认关联字段都有索引;超3张表关联且数据量大时,考虑在应用层分步查+内存组装
基本上就这些。不复杂,但容易忽略细节。优化不是一劳永逸,而是随着数据增长、查询变化持续观察和微调的过程。











