你在写SQL的时候,有没有遇到过明明语句不复杂,但跑起来就是慢?这时候光看代码看不出问题,得看看数据库是怎么执行它的。查询计划就是干这个用的——它告诉你数据库“打算怎么查”数据。
什么是查询计划
简单说,查询计划是数据库在执行SQL前生成的一套“操作步骤”。比如你要查一个用户订单,数据库可能选择先走索引、再关联表,或者全表扫描。这些动作都会体现在查询计划里。
常见的数据库如MySQL、PostgreSQL、SQL Server都支持查看查询计划,命令也差不多。以MySQL为例,只需要在SQL前面加个 EXPLAIN 就行。
EXPLAIN SELECT * FROM orders WHERE user_id = 1001;
怎么看输出结果
执行完 EXPLAIN,你会看到一张表格,关键字段有这几个:
- id:操作的序号,相同就按顺序执行,不同则外层先执行
- select_type:查询类型,比如简单查询(SIMPLE)、子查询(SUBQUERY)
- table:涉及哪张表
- type:访问类型,很重要!从好到差大概是:system → const → eq_ref → ref → range → index → ALL
- possible_keys:可能用到的索引
- key:实际用到的索引
- rows:预估扫描行数,越少越好
- Extra:额外信息,比如“Using where”“Using index”
举个例子,如果看到 type: ALL 且 rows 几万,基本就是全表扫描了。这时候你应该检查有没有给 WHERE 条件里的字段加索引。
重点关注哪些信号
有几个“危险信号”一出现就得留意:
type: ALL —— 全表扫描,数据量大时很慢。
Extra: Using filesort —— 需要额外排序,没走索引排序。
Extra: Using temporary —— 用了临时表,通常是 group by 或 distinct 操作没优化好。
比如你写了这么一句:
EXPLAIN SELECT user_id, COUNT(*) FROM orders GROUP BY user_id;
理想情况下,key 应该显示用了 user_id 的索引,而且 Extra 是 Using index,说明直接走了索引覆盖,不用回表。
进阶:用 EXPLAIN ANALYZE 看真实情况
有些数据库支持 EXPLAIN ANALYZE(如PostgreSQL),它不只是“计划”,而是真正执行一遍,告诉你实际耗时。
EXPLAIN ANALYZE SELECT * FROM orders WHERE create_time > '2024-01-01';
输出会包含每个步骤的真实执行时间,比普通EXPLAIN更准,但别在生产库随便用,毕竟真执行了。
小技巧:结合业务场景看
别光盯着技术指标。比如你查的是“最近一周订单”,哪怕扫了几千行,只要响应在100ms内,其实也能接受。反过来,一个管理后台每小时才跑一次的报表,就算慢点也没关系。
关键是搞清楚:这个SQL跑多少次?用户能不能感知延迟?数据量会不会持续增长?把这些和查询计划结合起来看,才能做出合理判断。
多看几次查询计划,你会发现一些常见套路。比如联合索引顺序不对,就可能用不上;where里对字段做函数操作,索引也会失效。这些都是能通过计划一眼识别的问题。