MySQL vs Hive:EXPLAIN 到底该怎么看?
前言
EXPLAIN 不是“语法糖”,而是唯一能让你提前看到 SQL 执行路径的官方工具。
把路径看懂,才知道慢在哪、该动索引还是动数据。
下面给出可落地的读法:先 MySQL,再 Hive,各自只有三个核心指标,记住就能用。
一、MySQL:看“查数据”的三板斧
1. 准备实验表
CREATE TABLE orders(
order_id BIGINT PRIMARY KEY,
user_id BIGINT,
amount DECIMAL(10,2),
KEY idx_uid (user_id)
)ENGINE=InnoDB;
2. 两条 SQL 对比
-- SQL-1 主键查
SELECT * FROM orders WHERE order_id = 12345;
-- SQL-2 普通列查
SELECT * FROM orders WHERE user_id = 12345;
3. 分别跑 EXPLAIN
EXPLAIN SELECT * FROM orders WHERE order_id = 12345\G
EXPLAIN SELECT * FROM orders WHERE user_id = 12345\G
4. 输出截断(只留关键列)
SQL-1
type: const
key: PRIMARY
rows: 1
Extra: NULL
SQL-2
type: ref
key: idx_uid
rows: 104
Extra: Using where
5. 怎么读这三列
| 列名 | 含义 | 安全阈值 | 超标怎么办 |
|---|---|---|---|
| type | 访问类型 | 至少达到 range 以上 | 出现 ALL 就全表扫描,必须加索引或改写 |
| key | 实际索引 | 必须不是 NULL | NULL = 没索引可用,考虑新建或更换索引 |
| rows | 预估行数 | 尽量 < 原表 5% | 过大说明索引区分度差,考虑联合索引或覆盖索引 |
6. 进阶:Extra 出现这 4 个词要警惕
-
Using filesort—— 内存/磁盘排序,ORDER BY 没走索引 -
Using temporary—— 建了临时表,GROUP/DISTINCT 没走索引 -
Range checked for each record—— 索引选择代价高,可能抖动 -
Using where; Using index—— 完美,覆盖索引不回表
7. 小结(背下来)
type ≠ ALL → key ≠ NULL → rows 足够小
满足这三条,MySQL 层面基本没大坑;任何一条破功,就加索引或改 SQL。
二、Hive:看“跑任务”的三板斧
1. 准备实验表
CREATE TABLE orders(
order_id BIGINT,
user_id BIGINT,
amount DECIMAL(10,2)
)
STORED AS ORC;
2. 一条聚合 SQL
SELECT user_id, COUNT(*) cnt
FROM orders
GROUP BY user_id;
3. 跑 EXPLAIN
EXPLAIN
SELECT user_id, COUNT(*) cnt
FROM orders
GROUP BY user_id;
4. 核心输出(Stage 依赖 + Stage plan)
STAGE DEPENDENCIES:
Stage-1 root
Stage-0 depends on Stage-1
STAGE PLANS:
Stage-1: Map
TableScan --> Reduce Output (hash distribute by user_id)
Stage-0: Reduce
Group By --> Final File Output
5. 怎么读这三点
| 检查点 | 含义 | 危险信号 | 调优动作 |
|---|---|---|---|
| Stage 数量 | 越多越慢 | >3 就要看 | 合并子查询、减少嵌套 |
| Map/Reduce 之间 | 有没有 Sort + Shuffle | 数据倾斜时 Reduce 极慢 | 加盐重写、开启 skew join |
| TableScan 行数 | 原始数据量 | 远大于分区过滤后行数 | 加分区、加 ORC bloom filter |
6. 两条实战命令辅助
-- 看真实输入行数
EXPLAIN DEPENDENCY ...;
-- 看运行时算子
EXPLAIN EXTENDED ...;
把 TableScan 后面的 rawDataSize 和 numRows 对比,就能知道分区下推有没有生效。
7. 小结(背下来)
Stage 少 → Shuffle 小 → TableScan 行数=分区过滤后行数
满足这三条,Hive 作业基本健康;否则就改分区、加盐或调并行度。
三、一张图总结(保存即可)
| 维度 | MySQL EXPLAIN | Hive EXPLAIN |
|---|---|---|
| 核心目标 | 避免全表扫描 | 避免多余 Stage/Shuffle |
| 关键指标 | type, key, rows | Stage 数、Shuffle 关键字、TableScan 行数 |
| 优化手段 | 加索引、覆盖索引、改写 SQL | 加分区、加盐、合并子查询、调并行度 |
| 典型危险 | type=ALL | Reduce 卡住、数据倾斜 |
四、给你一套“出问题时”的固定步骤
MySQL 慢
-
跑
EXPLAIN看 type/key/rows -
type=ALL → 新建索引
-
key=NULL → 检查列类型/字符集是否一致
-
rows 过大 → 建联合索引或限制返回列(覆盖索引)
Hive 慢
-
跑
EXPLAIN看 Stage 数 -
Stage>3 → 合并子查询、先
WITH tmp AS物化 -
看有没有
distribute by+sort by→ 倾斜时改加盐 -
TableScan行数远大于分区行数 → 加分区或ANALYZE TABLE更新元数据
五、结语
记住两句话,现场就不会慌:
-
MySQL 看“查”——别让 type 变成 ALL
-
Hive 看“跑”——别让 Stage 无限增加
把 EXPLAIN 当成体检报告,而不是参考书。报告只看关键指标,超标就动刀,别的花哨字段先忽略,优化自然有章法。
更多推荐



所有评论(0)