某日上午收到监控告警,发现一个日常ETL任务运行时间从平时的25分钟突然飙升到3小时以上,且最终以失败告终。该任务是一个典型的多表JOIN操作,涉及用户行为日志与元数据信息的关联计算。
通过YARN ResourceManager查看,发现该任务卡在reduce阶段99%的位置,最后一个reduce任务运行时间异常长,而其他reduce任务早已完成。Tez UI中显示该reduce任务处理的数据量高达120GB,而其他reduce任务平均处理数据量仅为1.2GB左右。
首先检查了当日数据量是否异常增长:
SELECT COUNT(*) FROM user_behavior_log WHERE dt='20230501';
结果显示数据量在正常范围内,排除了数据暴涨的可能性。
使用抽样方法检查JOIN键的数据分布:
SELECT join_key, COUNT(*) as cnt
FROM user_behavior_log
WHERE dt='20230501'
GROUP BY join_key
ORDER BY cnt DESC
LIMIT 10;
发现一个异常情况:NULL值的记录数异常多,达到了8亿条,占总数据量的40%左右。
查看Hive执行计划,确认数据倾斜发生在哪个环节:
EXPLAIN
SELECT a.user_id, b.user_info, COUNT(*)
FROM user_behavior_log a
JOIN user_meta_info b ON a.join_key = b.join_key
WHERE a.dt='20230501'
GROUP BY a.user_id, b.user_info;
从执行计划中发现,在reduce阶段需要进行大量的数据shuffle,而NULL值全部被分配到了同一个reduce任务中处理。
经过分析,问题根源在于:
首先对NULL值进行随机化处理,避免数据倾斜:
SET hive.exec.parallel=true;
SET hive.optimize.skewjoin=true;
SET hive.skewjoin.key=1000000;
SELECT
a.user_id,
b.user_info,
COUNT(*)
FROM (
SELECT
user_id,
CASE WHEN join_key IS NULL
THEN CONCAT('NULL_', CAST(RAND() * 100 AS STRING))
ELSE join_key
END AS join_key
FROM user_behavior_log
WHERE dt='20230501'
) a
JOIN user_meta_info b ON a.join_key = b.join_key
GROUP BY a.user_id, b.user_info;
hive.optimize.skewjoin
等相关参数,但要注意这些参数不是万能的为了避免类似问题再次发生,我们团队后续采取了以下措施:
这次排查经历让我们深刻认识到,在大数据处理中,数据质量管理和性能优化同样重要。一个好的数据开发工程师不仅要会写SQL,更要具备全链路的数据思维和问题排查能力。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。