Spark SQL查询导致巨大的数据洗牌读取/写入

时间:2018-06-21 11:16:56

标签: apache-spark pyspark apache-spark-sql pyspark-sql

我正在使用spark sql处理数据。这是查询

select 
    /*+ BROADCAST (C) */ A.party_id, 
    IF(B.master_id is NOT NULL, B.master_id, 'MISSING_LINK') as master_id, 
    B.is_matched, 
    D.partner_name, 
    A.partner_id, 
    A.event_time_utc, 
    A.funnel_stage_type, 
    A.product_id_set, 
    A.ip_address, 
    A.session_id, 
    A.tdm_retailer_id, 
    C.product_name ,
    CASE WHEN C.product_category_lvl_01 is NULL THEN 'OUTOFSALE' ELSE product_category_lvl_01 END as product_category_lvl_01,
    CASE WHEN C.product_category_lvl_02 is NULL THEN 'OUTOFSALE' ELSE product_category_lvl_02 END as product_category_lvl_02,
    CASE WHEN C.product_category_lvl_03 is NULL THEN 'OUTOFSALE' ELSE product_category_lvl_03 END as product_category_lvl_03,
    CASE WHEN C.product_category_lvl_04 is NULL THEN 'OUTOFSALE' ELSE product_category_lvl_04 END as product_category_lvl_04, 
    C.brand_name 
from 
    browser_data A 
    INNER JOIN (select partner_name, partner_alias_tdm_id as npa_retailer_id from npa_retailer) D  
        ON (A.tdm_retailer_id = D.npa_retailer_id) 
    LEFT JOIN 
        (identity as B1 INNER JOIN (select random_val from random_distribution) B2) as B 
        ON (A.party_id = B.party_id and A.random_val = B.random_val) 
    LEFT JOIN product_taxonomy as C 
        ON (A.product_id = C.product_id and D.npa_retailer_id = C.retailer_id)

在哪里, browser_data A-大约110 GB的数据,有5.19亿条记录,

D-小型数据集,仅映射到A中的一个值。由于这是小型Spark sql,因此会自动广播(在解释执行计划中确认)

B-具有4500万条记录的5 GB仅包含3列。该数据集被复制了30次(使用笛卡尔积,数据集包含0到29个值),从而解决了倾斜键(数据集A中的数据相对于一个)的问题,这将产生150 GB的数据。

C-900 MB,具有900万条记录。这与A通过广播连接(因此没有随机播放)连接在一起

以上查询效果很好。但是,当我看到Spark UI时,我可以观察到上述查询触发了6.8 TB的随机读取。由于数据集D和C以广播的形式连接在一起,因此不会引起任何混乱。因此,只有A和B的连接才可导致洗牌。即使我们考虑将所有数据混排读取,也应将其限制为110 GB(A)+ 150 GB(B)= 260 GB。为什么它会触发6.8 TB的随机数据读取和40 GB的随机数据写入。 任何帮助表示赞赏。预先谢谢你

谢谢

Manish

1 个答案:

答案 0 :(得分:0)

我要做的第一件事是在其上使用DataFrame.explain。这将向您显示执行计划,以便您可以确切地看到实际发生的情况。我将检查输出以确认广播联接确实正在发生。 Spark的设置可以控制您的数据在放弃广播联接之前的大小。

我还要指出,您对random_distribution的INNER JOIN看起来很可疑。我可能重新创建了您的架构错误,但是当我做了解释时我得到了:

scala> spark.sql(sql).explain
== Physical Plan ==
org.apache.spark.sql.AnalysisException: Detected cartesian product for INNER join between logical plans
LocalRelation [party_id#99]
and
LocalRelation [random_val#117]
Join condition is missing or trivial.
Use the CROSS JOIN syntax to allow cartesian products between these relations.;

最后,您的输入数据是否被压缩?您可能会看到大小差异,这是因为不再有数据不再被压缩,以及由于数据的序列化方式所致。