繁体   English   中英

Scala Spark isin 广播列表

[英]Scala Spark isin broadcast list

我正在尝试尽可能优化地执行 isin 过滤器。 有没有办法使用 Scala API 广播 collList?

编辑:我不是在寻找替代方案,我知道他们,但我需要 isin 所以我的 RelationProviders 会下推这些值。

  val collList = collectedDf.map(_.getAs[String]("col1")).sortWith(_ < _)
  //collList.size == 200.000
  val retTable = df.filter(col("col1").isin(collList: _*))

我传递给“isin”方法的列表最多有 200.000 个唯一元素。

我知道这看起来不是最好的选择,并且 join 听起来更好,但是我需要将这些元素推入过滤器中,这在阅读时会产生巨大的影响(我的存储是 Kudu,但它也适用于 HDFS+Parquet,base数据太大,查询只能处理大约 1% 的数据) ,我已经测量了所有内容,它为我节省了大约 30 分钟的执行时间:)。 另外,如果 isin 大于 200.000,我的方法已经很小心了。

我的问题是,我收到一些 Spark“任务太大”(每个任务约 8mb)警告,一切正常,所以没什么大不了的,但我希望删除它们并进行优化。

我试过了,它什么也没做,因为我仍然收到警告(因为广播的 var 在 Scala 中得到解决并传递给我猜的 vargargs):

  val collList = collectedDf.map(_.getAs[String]("col1")).sortWith(_ < _)
  val retTable = df.filter(col("col1").isin(sc.broadcast(collList).value: _*))

而这个不编译:

  val collList = collectedDf.map(_.getAs[String]("col1")).sortWith(_ < _)
  val retTable = df.filter(col("col1").isin(sc.broadcast(collList: _*).value))

而这个不起作用(任务太大仍然出现)

  val broadcastedList=df.sparkSession.sparkContext.broadcast(collList.map(lit(_).expr))
  val filterBroadcasted=In(col("col1").expr, collList.value)
  val retTable = df.filter(new Column(filterBroadcasted))

关于如何广播这个变量的任何想法? (允许黑客攻击)。 允许过滤器下推的 isin 的任何替代方法也是有效的我见过有人在 PySpark 上这样做,但 API 不一样。

PS:不可能对存储进行更改,我知道分区(已经分区,但不是按该字段)等可能会有所帮助,但是用户输入是完全随机的,并且数据被访问并更改了我的许多客户端。

在这种情况下,我会选择 dataframe 广播 hash 加入而不是广播变量。

准备一个 dataframe 和您想要使用isin过滤的collectedDf("col1")集合列表,然后使用两个数据帧之间的连接来过滤匹配的行。

在此处输入图像描述

我认为它会比isin更有效,因为您有 200k 条目要过滤。 spark.sql.autobroadcastjointhreshhold是您需要设置适当大小的属性(默认为 10mb)。 AFAIK 您可以根据您的要求使用到 200mb 或 3oomb。

看到这个 BHJ 解释它是如何工作的

进一步阅读Spark 有效地过滤来自小型 dataframe 中的大型 dataframe 的条目

我只会带着大任务离开,因为我在我的程序中只使用了两次(但节省了很多时间),而且我负担得起,但如果其他人非常需要它......好吧,这似乎是路径。

我发现有大阵列下推的最佳替代方案:

  1. 更改您的关系提供程序,以便在按下过滤器时广播大列表,这可能会留下一些广播垃圾,但是...,只要您的应用程序没有流式传输,这应该不是问题,或者您可以保存在全局列表中并在一段时间后清理它们
  2. 在 Spark 中添加一个过滤器(我在https://issues.apache.org/jira/browse/SPARK-31417中写了一些东西),它允许广播下推到您的关系提供者 您必须添加您的自定义谓词,然后实现您的自定义“下推”(您可以通过添加新规则来做到这一点),然后重写您的 RDD/Relation 提供程序,以便它可以利用变量被广播的事实。
  3. 阅读后使用 coalesce(X) 减少任务数量,有时可以工作,取决于 RelationProvider/RDD 的实现方式

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM