Spark增强数据集之间的TB级连接

时间:2019-05-19 12:54:34

标签: scala apache-spark

我有五个Hive表,假设名称分别是A,B,C,D和E。对于每个表,都有一个customer_id作为它们之间连接的键。另外,每个表至少包含100:600列,所有列均为Parquet格式。

下表的示例:

CREATE TABLE table_a 
(
customer_id Long, 
col_1 STRING,
col_2 STRING,
col_3 STRING,
.
.
col_600 STRING
)
STORED AS PARQUET;

我需要达到两点,

  • 使用Spark Scala以最佳方式将所有这些成员加入。加入之前,我曾尝试sortByKey,但仍然存在性能瓶颈。在加入之前,我尝试通过键reparation进行操作,但是性能仍然不佳。我试图提高Spark的并行度,使其具有许多执行者使其达到6000,但无法取得良好的结果。
  • 加入后,我需要为其中一些列应用单独的功能。

我在下面尝试的联接示例

val dsA =  spark.table(table_a)
val dsB =  spark.table(table_b) 
val dsC =  spark.table(table_c) 
val dsD =  spark.table(table_d) 
val dsE =  spark.table(table_e) 
val dsAJoineddsB = dsA.join(dsB,Seq(customer_id),"inner")

1 个答案:

答案 0 :(得分:0)

我认为在这种情况下,直接联接不是最佳情况。您可以使用以下简单方法来完成此任务。

  • 首先,创建具有两个字段FeatureData的案例类case class FeatureData(customer_id:Long, featureValue:Map[String,String])
  • 第二,您将每个表映射到FeatureData案例类键[feature_name,feature_value]
  • 第三,您将groupByKeyunion所有具有相同键的数据集。

我以上述方式进行合并比加入要快。但是它需要做更多的工作。

在那之后,您将拥有一个包含键映射的数据集。您将对key, Map(feature_name)应用转换。

实现的简单示例如下: 您将首先将dataset映射到case class,然后可以合并所有它们。之后,您将groupByKey然后将其映射并缩小。

case class FeatureMappedData(customer_id:Long, feature: Map[String, String])
val dsAMapped = dsA.map(row ⇒
        FeatureMappedData(row.customer_id,
          Map("featureA" -> row.featureA,
            "featureB" -> row.featureB)))
val unionDataSet = dsAMapped  union dsBMapped 
unionDataSet.groupByKey(_.customer_id)
      .mapGroups({
        case (eid, featureIter) ⇒ {
      val featuresMapped: Map[String, String] = featureIter.map(_.feature).reduce(_ ++ _).withDefaultValue("0") 
      FeatureMappedData(customer_id, featuresMapped)
    }
  })