查询突然变慢了,怎么快速定位问题?——执行计划分析和性能排查
先说结论
排查思路:先看执行计划EXPLAIN,确认是否走了索引分区剪枝;再看Spark UI找到慢的阶段Stage;最后看慢的任务Task定位具体原因.
关键指标:Shuffle Read Write数据量、Task执行时间、GC时间、Spark UI的SQL标签页查看执行计划.
常见原因:数据倾斜某个Task特别慢、小文件太多Driver收集文件慢、谓词下推失效扫描过多数据、Join策略错误.
最佳实践:定期收集统计信息ANALYZE TABLE、监控慢查询、设置合理的并行度、启用AQE自适应查询.
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
这道题面试官问得很多,因为查询突然变慢是生产环境最常见的问题之一。我在某出海硬件品牌遇到过昨天还跑1分钟的查询今天花了10分钟的问题。很多人只知道看Spark UI,但说不清楚怎么看执行计划。面试官想听的是你能说清楚排查思路和实战经验.
真实案例:查询从1分钟变成10分钟
2023年在某知名出海硬件品牌,我们的用户行为分析查询突然变慢了.
SELECT user_id, event_type, COUNT(*) as event_count
FROM user_behavior
WHERE dt = '2024-03-19'
GROUP BY user_id, event_type;
这个查询平时运行时间约1分钟,但某天突然花了10分钟.
排查步骤1:查看执行计划用EXPLAIN查看执行计划.
排查步骤2:查看Spark UI打开Spark UI查看Stages页面,发现Stage 2 Aggregate阶段花了9分30秒,有200个Task,其中199个Task花了10秒,但有1个Task花了9分钟.
定位问题:这是典型的数据倾斜问题。某个user_id的数据量特别大,导致那个Task特别慢.
# Spark UI显示的Task执行时间
Stage 2 (Aggregate):
Task 1: Duration: 10 seconds (100万行)
Task 2: Duration: 10 seconds (100万行)
...
Task 199: Duration: 10 seconds (100万行)
Task 200: Duration: 540 seconds (5000万行!) <- 这个Task特别慢
解决方案:过滤掉爬虫数据,增加shuffle分区数从200加到400。改后查询时间从10分钟降到1分钟.
// 解决方案:增加shuffle分区数
spark.conf.set("spark.sql.shuffle.partitions", "400") // 从200加到400
// 过滤爬虫数据
val result = spark.sql("""
SELECT user_id, event_type, COUNT(*)
FROM user_behavior
WHERE dt = '2024-03-19'
AND user_agent NOT LIKE '%bot%'
GROUP BY user_id, event_type
""")
执行计划分析怎么看
执行计划Execution Plan是Spark SQL的执行蓝图。通过df.explain或Spark UI的SQL标签页可以查看.
// 查看执行计划的三种方式
val df = spark.sql("SELECT * FROM user_behavior WHERE dt='2024-03-19'")
// 1) 简单执行计划
df.explain()
// 2) 详细执行计划(推荐)
df.explain(extended = true)
// 3) Spark UI的SQL标签页(可视化)
执行计划的关键部分:1)Scan数据源扫描:看是否有PartitionFilters分区剪枝和PushedFilters谓词下推;2)Exchange Shuffle:看Shuffle方式;3)Aggregate聚合:看是否部分聚合.
// 执行计划示例(标注关键部分)
== Physical Plan =
* Project ... -- 投影(选择列)
* HashAggregate ... -- 聚合(GROUP BY)
+- Exchange ... -- Shuffle(数据交换)
+- * HashAggregate ... -- 部分聚合
+- * Filter ... -- 过滤(WHERE)
+- * Scan ... -- 扫描表
// 关键指标:
// 1) Scan后面的PartitionFilters:分区剪枝
// 2) Filter后面的PushedFilters:谓词下推
// 3) Exchange后面的数量:Shuffle分区数
Spark UI怎么看
Jobs页面:查看作业的整体进度。可以看到每个Job的Status和Duration。如果某个Job特别慢,点击进入查看详情.
Stages页面:查看每个Stage的执行情况。关键指标:如果某个Stage的Duration特别长,或者Task执行时间差异很大数据倾斜,就是问题所在.
Storage页面:查看缓存的表。可以看到哪些表被缓存了、缓存的大小.
SQL标签页:查看SQL的执行计划可视化。比df.explain更直观,可以看到每个操作的数据量、耗时.
Executors页面:查看Executor的状态。可以看到每个Executor的内存使用、GC时间、磁盘使用。如果GC时间特别高(大于10%),说明内存不够.
常见性能问题和解决方案
| 问题 | 症状 | 原因 | 解决方案 |
|---|---|---|---|
| 数据倾斜 | 某个Task特别慢 | 某个key的数据量特别大 | 加盐、增加分区数、过滤倾斜数据 |
| 小文件太多 | Driver收集文件慢 | 每个分区只有几MB | OPTIMIZE合并小文件 |
| 谓词下推失效 | Scan阶段慢 | 使用UDF或子查询 | 改写SQL、避免UDF |
| Join策略错误 | Exchange慢 | 大表Join没用Broadcast | 调整autoBroadcastJoinThreshold |
| 内存不足 | GC时间长OOM | 数据量超过内存 | 增加Executor内存 |
面试高频追问
追问一:如何快速定位数据倾斜?
看Spark UI的Stages页面,找到Duration最长的Stage,点击进去查看Task列表。如果某个Task的Duration是其他Task的10倍以上,且Input Output数据量也大很多,就是数据倾斜.
追问二:谓词下推失效了怎么排查?
用df.explain查看执行计划,看Filter操作后面是否有PushedFilters。如果没有,说明谓词下推失效。常见原因:使用UDF、过滤条件包含子查询、统计信息过期.
追问三:Shuffle Read Write数据量多少算过大?
如果Shuffle数据量大于表总大小的50%,说明Shuffle了很多数据,可能需要优化Join方式用Broadcast Join。如果某个Stage的Shuffle特别大其他Stage的10倍,说明有数据倾斜.
实战踩坑:谓词下推失效导致查询超时
2023年在某出海硬件品牌,我们遇到过谓词下推失效导致查询超时的问题。age列是通过UDF计算的.
// 问题代码:age列通过UDF计算
spark.udf.register("calcAge", (birthday: String) => ...)
val df = spark.sql("SELECT *, calcAge(birthday) as age FROM user_behavior")
// 执行计划显示:
// * Filter (age > 25) -- 没有PushedFilters!
// +- Scan user_behavior -- 谓词下推失效
排查发现:因为age列是通过UDF计算的,谓词下推无法生效,Spark需要在读取所有数据后才能过滤age大于25的数据.
解决方案:我们做了两件事:1)将age列存储到user_behavior表(而不是通过UDF计算);2)收集统计信息ANALYZE TABLE。改后查询时间从超时降到1分钟.
-- 改进方案:将age列存储到表中
-- 1)修改ETL,将age列写入user_behavior
INSERT INTO user_behavior
SELECT ub.*, u.age
FROM user_behavior_staging ub
JOIN users u ON ub.user_id = u.user_id;
-- 2)收集统计信息
ANALYZE TABLE user_behavior COMPUTE STATISTICS FOR COLUMNS age;
改进效果:改后谓词下推生效,查询性能大幅提升.
总结
查询突然变慢的排查思路是:先看执行计划EXPLAIN,确认分区剪枝和谓词下推是否生效;再看Spark UI找到慢的阶段Stage和慢的任务Task;最后定位具体原因。关键指标是:Shuffle Read Write数据量、Task执行时间、GC时间。最佳实践是:定期收集统计信息、监控慢查询、设置合理的并行度。面试时能说清楚排查思路、执行计划怎么看、常见问题及解决方案,就很稳.
下一篇聊一个很多人问的问题:Delta Lake、Iceberg、Hudi怎么选?——三大数据湖格式对比和选型指南
你们生产环境遇到过查询突然变慢的问题吗?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长