在pyspark中的SQL中广播多视图

时间:2018-07-28 13:15:21

标签: pyspark broadcast

我想在与一个大表连接时在多个小表上使用BROADCAST提示。在下面的示例中,SMALLTABLE2在不同的连接列上与LARGETABLE进行了多次连接。现在要获得更好的性能,我希望同时广播SMALLTABLE1和SMALLTABLE2。是否可以通过简单地添加提示/ * BROADCAST(B,C,D,E)* /来实现,还是有更好的解决方案?我正在通过查询Dataframe中的HIVE表,然后使用createOrReplaceTempView创建一个视图作为SMALLTABLE1和SMALLTABLE2来获取数据。稍后将在下面的查询中使用。

反正使用createOrReplaceTempView函数创建的广播视图吗?

SELECT A.COL1, A.COL2, A.COL3, B.COL4, C.COL5, D.COL6, E.COL7
FROM LARGETABLE A
JOIN SMALLTABLE1 B
ON A.LCOL = B.SCOL
JOIN SMALLTABLE2 C
ON A.LCOL1 = C.SCOL
JOIN SMALLTABLE2 D
ON A.LCOL2 = D.SCOL
JOIN SMALLTABLE2 E
ON A.LCOL3 = E.SCOL

1 个答案:

答案 0 :(得分:0)

如果您使用的是spark 2.2+,则可以使用以下任何MAPJOIN/BROADCAST/BROADCASTJOIN提示。

有关此功能的更多详细信息,请参见this Jira和this

  

示例:下面我使用了广播,但是您可以使用 mapjoin / broadcastjoin 提示将产生相同的解释计划。

>>> spark.range(1000000000).createOrReplaceTempView("t")
>>> spark.range(1000000000).createOrReplaceTempView("u")
>>>sql("select /*+ Broadcast(t,u) */* from t join u on t.id=u.id").explain()
== Physical Plan ==
*BroadcastHashJoin [id#0L], [id#16L], Inner, BuildRight
:- *Range (0, 1000000000, step=1, splits=56)
+- BroadcastExchange HashedRelationBroadcastMode(List(input[0, bigint, false]))
   +- *Range (0, 1000000000, step=1, splits=56)

(或)

如果您使用的是Spark <2,那么我们需要使用dataframe API进行持久化,然后注册为可以在内存连接中实现的临时表。

>>> df=hc.range(10000000)
>>> df.persist() --persist the df in memory
>>> df.registerTempTable("u") --register temp table
>>> df1=hc.range(10000000)
>>> df1.persist()
>>> df1.registerTempTable("t")
>>> hc.sql("select * from t join u on t.id=u.id").explain()
== Physical Plan ==
Project [id#11L,id#26L]
+- SortMergeJoin [id#11L], [id#26L]
   :- Sort [id#11L ASC], false, 0
   :  +- TungstenExchange hashpartitioning(id#11L,200), None
   :     +- InMemoryColumnarTableScan [id#11L], InMemoryRelation [id#11L], true, 10000, StorageLevel(false, true, false, false, 1), ConvertToUnsafe, None
   +- Sort [id#26L ASC], false, 0
      +- TungstenExchange hashpartitioning(id#26L,200), None
         +- InMemoryColumnarTableScan [id#26L], InMemoryRelation [id#26L], true, 10000, StorageLevel(false, true, false, false, 1), ConvertToUnsafe, None
  

使用DataFrames而不创建任何临时表

>>>from pyspark.sql.functions import *
>>> df=hc.range(10000000)
>>> df1=hc.range(10000000)
>>> df.join(broadcast(df1),['id']).explain()
== Physical Plan ==
Project [id#26L]
+- BroadcastHashJoin [id#26L], [id#11L], BuildRight
   :- ConvertToUnsafe
   :  +- Scan ExistingRDD[id#26L]
   +- ConvertToUnsafe
      +- Scan ExistingRDD[id#11L]

此外,广播联接是在Spark中自动完成的。

有一个参数“ spark.sql.autoBroadcastJoinThreshold ”,默认设置为 10mb

然后要更改默认值

conf.set("spark.sql.autoBroadcastJoinThreshold", 1024*1024*<mb_value>)

有关更多信息,请参见与{strong> spark.sql.autoBroadcastJoinThreshold 的this链接。