执行计划是优化SQL的第一步,必须先用EXPLAIN等命令分析;若出现全表扫描或统计信息偏差大,应先ANALYZE而非盲目加索引;复合索引字段顺序、函数滥用、低效分页等均会导致索引失效。

先看执行计划,再动索引
没有执行计划就加索引,大概率白忙活。MySQL 的 EXPLAIN、PostgreSQL 的 EXPLAIN ANALYZE、SQL Server 的 SET STATISTICS XML ON,都是必须第一步跑的命令。重点看 type(MySQL)或 Node Type(PG),如果出现 ALL 或 Seq Scan,说明走了全表扫描;再看 rows 预估和实际行数是否偏差极大——这往往意味着统计信息过期,ANALYZE 比加索引更紧迫。
- 别只盯着“有没有用上索引”,更要关注“用了哪个索引”和“用了几层索引条件”
- 复合索引字段顺序不对,
WHERE a = ? AND b > ?用(b, a)就基本失效 - 某些 ORM 自动生成的
ORDER BY RAND()或LIMIT 10000 OFFSET 10000,加索引也救不了,得换逻辑
WHERE 条件里的函数调用是隐形杀手
WHERE YEAR(created_at) = 2023 或 WHERE UPPER(name) = 'JOHN' 会让索引完全失效。数据库无法用 B+ 树直接匹配函数结果,只能回表或全扫。
- 改写为范围查询:
created_at >= '2023-01-01' AND created_at - 需要大小写不敏感查询,建函数索引(PG/Oracle 支持
CREATE INDEX ON users ((UPPER(name)));MySQL 8.0+ 支持函数索引,但需注意表达式必须确定性 -
LIKE '%abc'无法走索引,LIKE 'abc%'可以——如果业务真要前缀模糊,考虑倒排或全文索引
JOIN 顺序和驱动表选错,索引也白搭
优化器不总是对的。小表驱动大表仍是硬道理,尤其在 MySQL 中,STRAIGHT_JOIN 有时比依赖优化器更稳。看 EXPLAIN 的 table 列顺序和 rows 乘积,如果驱动表预估返回 10 万行,被驱动表即使有索引,也要做 10 万次索引查找+回表,I/O 压力爆炸。
极速网店升级内容:1.网店系统升级到Net2.0框架2.网店系统架构升级,使系统速度提升30%3.修正购物车下一步容易出错的问题4.修正会员删除的Bug5.修正广告时间不能选择的问题6.修正程序的兼容问题2008版升级内容如下:1、修正打SP2后用户登陆时出错的问题;2、修正用户列表错误的问题;3、修正程序的兼容性问题;4、修正用户Cookie加密码乱码的问题5、修正程序中存在的小BUG;6、优化
- 确保 JOIN 字段类型严格一致:一个是
INT,一个是BIGINT,或一个是VARCHAR(50)、一个是VARCHAR(100),都可能导致隐式转换,跳过索引 - 多表 JOIN 时,优先把带高选择性过滤条件(如
status = 'paid')的表放在前面作为驱动表 - 临时表(
SELECT ... FROM (SELECT ...) t)默认无索引,必要时用 CTE +MATERIALIZED(PG 12+)或物化中间结果
避免 SELECT * 和 N+1 查询
查 100 行却返回 50 列,其中 45 列根本不用,不仅网络和内存浪费,还可能让覆盖索引失效(因为要回表取没索引的字段)。更隐蔽的是 ORM 中的懒加载:一个 users 查询后,循环里调 user.posts,触发 N 次 SQL。
- 显式列出所需字段,尤其是宽表场景下,能显著减少 Buffer Pool 压力
- 用
JOIN一次性拉取关联数据,或用批量 ID 查询(WHERE post.user_id IN (1,2,3...))替代循环单查 - PostgreSQL 中
SELECT COUNT(*)在大表上极慢?确认是否真需要精确值——很多场景用估算值(pg_class.reltuples)就够了
真实瓶颈常藏在「看起来最不该出问题」的地方:比如一个加了索引的字段,因字符集不同导致连接失效;或者一个 ORDER BY 字段没进索引,却让整个执行计划退化成 filesort。优化不是线性流程,而是反复对照执行计划、验证假设、缩小范围的过程。










