Spark SQL JOIN 异常问题调优(Hint方式)

1.大表关联小表 (显式广播小表)

在SQL中加入广播的提示

示例:

-- test_table_a row_count=1000W
-- test_table_b row_count=500

SELECT /*+ BROADCAST(t2) */
t1.id
,t2.name
FROM test_table_a t1
LEFT JOIN test_table_b t2
ON t1.id = t2.id


这里的 /*+ BROADCAST(t2) / 也可以写成 /+ BROADCASTJOIN (t2) / ,/+ MAPJOIN (t1) */


*以下仅适用于spark3.0 及以上版本

2. 解决SQL中关联时某个字段存在数据倾斜的情况

对关联某个关联字段进行拆分

示例:

-- test_main_table:city_code字段分布情况: C001:1000w条记录,其他的code每个平均100条记录
-- test_city_table: 维表,code作为主键,不会重复
-- 不加提示的情况下会产生数据倾斜的情况,一个task在running这1000w条记录,导致整个任务运行很久,或者导致executor OOM

SELECT /*+ REPARTITION_BY_RANGE(32, city_code) */
t1.city_code
, t2.city_name
FROM test_main_table t1
LEFT test_city_table t2
ON t1.city_code = t2.code


加入/*+ REPARTITION_BY_RANGE(32, city_code) /可以始得在关联的时候对主表的city_code进行重新分区,划分成32个分区,从而解决数据倾斜问题,同样的这个hint还可以写成:/+ REPARTITION_BY_RANGE© /,/+ REPARTITION(3, c) */


3.控制SQL结果输出数据文件个数

需要指定SQL输出的数据文件分区个数

示例

SELECT /*+ REPARTITION(8) */
*
FROM test_table


当加入 /*+ REPARTITION(8) / 提示就会始最终数据的文件块变为8,同样的提示还有:/+ COALESCE(8) */,两者的区别在于前者会进行shuffle开销,而后者却不会.


4.解决异常广播问题

强制关联过程中不使用广播

示例:

-- test_table_a row_count=1000W
-- test_table_b row_count=900w
-- 在关联的过程中由于表元数据信息记录有误,导致spark将t2表误解成了小表进行了广播.

SELECT /*+ SHUFFLE_MERGE(t2) */
t1.id
,t2.name
FROM test_table_a t1
LEFT JOIN test_table_b t2
ON t1.id = t2.id


当加入 /*+ SHUFFLE_MERGE(t1) / 提示后,spark 会强制对t1于t2的关联转换成shuffle sort merge join的模式,从而解决大表被广播的异常,等同的提示还有 /+ MERGEJOIN(t2) /,/+ MERGE(t1) */


​详细请参考spark官方文档​