点“解释”无执行计划,先查数据库版本兼容性、explain语句格式及用户权限;join中type=all且key=null表明未走索引、正全表扫描。
navicat里点“解释”没出执行计划,先查这三件事
navicat 本身不生成执行计划,它只是把 explain 语句发给数据库。点“解释”没反应或报错,大概率不是 navicat 的问题,而是数据库端卡住了。
- MySQL 用户:确认版本 ≥ 5.6,且语句不是
INSERT ... SELECT、存储过程调用、或带子查询的UNION—— 这些在旧版中不支持EXPLAIN - PostgreSQL 用户:Navicat 默认只发
EXPLAIN,不带实际执行数据。要看到真实耗时和缓存命中,必须手动改成EXPLAIN (ANALYZE, BUFFERS) - 权限检查:MySQL 需
SELECT权限,某些版本还要求PROCESS;PG 需能访问pg_stat_statements视图
JOIN 执行计划里 type=ALL 和 key=NULL 是什么信号
这两项同时出现,基本等于宣告“这个 JOIN 没走索引,正在全表扫描”。不是警告,是确诊。
-
type=ALL表示 MySQL 对该表逐行读取,哪怕只有 1 万行,在 JOIN 中被外层驱动多次,性能会指数级恶化 -
key=NULL说明优化器压根没选任何索引——哪怕表上明明建了索引,也可能因字段顺序、隐式转换或统计信息过期而被忽略 - 特别注意
possible_keys有值但key为空:常见于WHERE条件用了函数(如YEAR(create_time)=2023),应改写为范围查询create_time >= '2023-01-01' AND create_time
怎么判断 JOIN 是不是用了 Hash Join 或 Sort_merge_join
Navicat 不直接显示算法名称,得靠 Extra 和 type 组合推断。
- MySQL 8.0+ 出现
Using join buffer (hash join)在Extra列,且Type显示为Hash Join,说明已启用 Hash Join —— 通常发生在被驱动表无索引、或优化器估算 NLJ 成本过高时 - Sort_merge_join 在 MySQL 的执行计划中不会直写,但若看到
type=ALL或type=range配合Extra=Using join buffer,且rows值很大,大概率就是它在后台排序合并 - 验证是否真触发 Hash Join:执行
SELECT @@optimizer_switch;确认含hash_join=on;若需强制测试,加 HintSELECT/*+ NO_INDEX(t2) */ * FROM t1 JOIN t2 ON ...,注意表名必须用 SQL 中实际使用的别名
嵌套 JOIN 或多表关联时 rows 值为何突然爆炸
执行计划里的 rows 是优化器估算值,但当它远超单表总行数,尤其在嵌套结构中,往往意味着“某一层被反复调用”。
- 看
id列:id 越大越先执行;若子查询 id=2,外层 id=1,且子查询type=ALL、rows=10000,而外层结果有 500 行,则实际可能执行了 500 × 10000 次扫描 - 警惕
Extra中的Using temporary; Using filesort:这不是 ORDER BY 的问题,是 JOIN 阶段被迫落盘排序,sort_buffer_size默认仅 256KB,稍大点的数据就溢出 - 真正有效的动作不是调参数,而是拆解:把
SELECT * FROM (SELECT ... FROM t1 JOIN t2 ...) t改成独立语句,对内层单独EXPLAIN,定位哪一层开始失控
复杂 JOIN 的执行计划里,rows 和 Extra 的组合比单看 type 更危险——它不告诉你“慢”,而是在告诉你“慢多少倍”。











