Spark Dataset联接性能

时间:2019-07-12 01:37:12

标签: apache-spark hadoop apache-spark-sql apache-spark-dataset

我收到一个数据集,并且需要join和另一个表一起使用。因此,我想到的最简单的解决方案是为另一个表创建第二个数据集并执行joinWith

    def joinFunction(dogs: Dataset[Dog]): Dataset[(Dog, Cat)] = {
      val cats: Dataset[Cat] = spark.table("dev_db.cat").as[Cat]
      dogs.joinWith(cats, ...)
    }

在这里,我主要关注的是 spark.table("dev_db.cat") ,因为我们好像将所有cat数据都称为

    SELECT * FROM dev_db.cat

,然后在以后执行join。还是查询优化器将直接执行联接而不引用整个表?有更好的解决方案吗?

2 个答案:

答案 0 :(得分:1)

您需要做一个解释,看看是否使用谓词下推。然后,您可以判断您的担忧是否正确。

但是,通常现在,如果不使用复杂的数据类型和/或不明显的数据类型不匹配,则会发生下推。您也可以通过简单的createOrReplaceTempView看到它。参见https://databricks-prod-cloudfront.cloud.databricks.com/public/4027ec902e239c93eaaa8714f173bcfc/3741049972324885/4201913720573284/4413065072037724/latest.html

答案 1 :(得分:1)

以下是针对您的情况的一些建议:

a。。如果您有wherefilterlimittake等操作,请尝试在合并两个数据集之前应用它们。 Spark无法压低此类筛选器,因此您必须自己减少目标记录的数量。 Here是Spark优化程序的绝佳信息来源。

b。。尝试使用repartition函数来定位数据集并最小化混洗的数据。重新分区应基于参与join的密钥,即:

dogs.repartition(1024, "key_col1", "key_col2")
dogs.join(cats, Seq("key_col1", "key_col2"), "inner")

c。。如果您确定较小的数据集可以容纳在内存中(或增加broadcast的值),请尝试对较小的数据集使用spark.broadcast.blockSize。这将确保您的Spark程序具有一定的性能提升,因为它将确保同一节点内的两个数据集共存。

如果您不能应用上述任何一项,则Spark无法知道应该排除哪些记录,因此将扫描两个数据集中的所有可用行。