Spark中Broadcast Hash Join任务执行时间差异过大的原因
大表存在数据倾斜
即便小表已广播到所有Worker,大表的分区数据量可能差异极大。比如某个分区的数据量是其他分区的10倍以上,这个分区对应的任务需要处理更多数据,和广播表做非等值匹配的计算量自然更大,执行时间也就更长。非等值连接不依赖连接键分区,若大表的分区策略未做优化(比如随机分区时运气不佳导致数据扎堆),就会出现这种情况。非等值连接的匹配复杂度不一致
不同分区的大表数据,和广播小表的匹配次数、计算逻辑复杂度可能天差地别。比如做范围连接时,某分区的所有数据刚好落在小表的多个区间范围内,每条数据都要和小表的多条记录做比较;而另一个分区的数据只匹配小表的少数记录。这种匹配次数的差异会直接导致任务执行时间拉开差距。Worker/Executor资源不均衡
各个Worker节点的硬件性能(CPU核心数、内存大小、磁盘IO速度)可能不一样,或者某个Worker上同时运行了其他任务抢占资源。即使处理的数据量差不多,资源差的节点上的任务执行速度也会更慢。比如某台机器的CPU负载已经到90%,而其他机器只有30%,那这台机器上的Spark任务肯定跑不快。广播表的本地缓存未命中
Spark会把广播表缓存到Worker的内存中,但如果某个任务所在的Executor是刚启动的,或者之前的缓存被清理(比如内存不足被驱逐),这个任务就需要重新从Driver拉取广播表并加载到内存,额外增加了IO和初始化时间,导致执行时间变长。分区内数据的预处理差异
大表不同分区的数据可能存在预处理开销的差异:比如有的分区有大量需要类型转换的数据(非等值连接时类型不匹配需要转换),或者前置过滤条件的命中比例不同——有的分区过滤后剩下的数据很少,有的几乎没过滤,实际处理的数据量差异会直接反映在执行时间上。
内容的提问来源于stack exchange,提问作者Bibzon

