Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Join 加入数据帧,在Spark 1.5.2的物理计划中创建CartesianProduct_Join_Apache Spark_Dataframe_Apache Spark Sql_Cartesian - Fatal编程技术网

Join 加入数据帧,在Spark 1.5.2的物理计划中创建CartesianProduct

Join 加入数据帧,在Spark 1.5.2的物理计划中创建CartesianProduct,join,apache-spark,dataframe,apache-spark-sql,cartesian,Join,Apache Spark,Dataframe,Apache Spark Sql,Cartesian,当使用spark avro库连接从avro文件创建的数据帧时,我遇到了性能问题 数据帧由120K avro文件创建,总大小约为1.5 TB。 这两个数据帧非常巨大,包含数十亿条记录 这两个数据帧的连接将永远运行。 该流程在一个具有300个执行器、4个执行器芯和8GB内存的纱线簇上运行 任何关于这次加入的见解都会有所帮助。我已经在下面发布了解释计划。 我注意到实物平面图中有一个Cartesian产品。我想知道这是否是导致性能问题的原因 下面是逻辑计划和物理计划。(由于保密性质,我无法在此发布任何列

当使用spark avro库连接从avro文件创建的数据帧时,我遇到了性能问题

数据帧由120K avro文件创建,总大小约为1.5 TB。 这两个数据帧非常巨大,包含数十亿条记录

这两个数据帧的连接将永远运行。 该流程在一个具有300个执行器、4个执行器芯和8GB内存的纱线簇上运行

任何关于这次加入的见解都会有所帮助。我已经在下面发布了解释计划。 我注意到实物平面图中有一个Cartesian产品。我想知道这是否是导致性能问题的原因

下面是逻辑计划和物理计划。(由于保密性质,我无法在此发布任何列名或文件名)

代码如下所示

val customerDateFormat=新的SimpleDateFormat(“yyyy/MM/dd”)

val dates=新零售日期()
val dataStructures=新数据结构()
//读取CSV格式的输入文件--零售日期
//这个DF有75条记录
val retailDatesWithSchema=sqlContext.read
.format(“com.databricks.spark.csv”)
.选项(“分隔符“,”,”)
.schema(dates.retailDatesSchema)
.load(日期文件)
.合并(1)
.cache()
//创建自定义项以将字符串转换为日期
val dateUDF:(String=>java.sql.Date)=(dateString:String)=>new java.sql.Date(customerDateFormat.parse(dateString.getTime())
val stringToDateUDF=udf(日期udf)
//读取Avro格式的输入文件
//这个DF有5亿条记录
val userInputDf=sqlContext.read.avro(“customerLocation”)
val userDf=userInputDf.withColumn(“CAL_DT”),stringToDateUDF(col(“CAL_DT”))。选择(
“CAL_DT”、“用户ID”、“用户证书ID”
)
val userDimDf=sqlContext.read.avro(userDimFiles)。选择(“USER\u ID”、“USER\u CNTRY\u ID”、“PRIMARY\u USER\u ID”)//此DF有8亿条记录
val retailDatesWithSchemaBroadcast=sc.broadcast(retailDatesWithSchema)
val userDimDfBroadcast=sc.broadcast(userDimDf)
val userandetaildates=userDnaSdDf
.join((retailDatesWithSchemaBroadcast.value).as(“retailDates”),
在($“retailDates.WEEK\u BEGIN\u DATE”、$“retailDates.WEEK\u END\u DATE”)之间的userDf(“CAL\u DT”)
“内部”)
val userAndRetailDates和userdim=userAndRetailDates
.join((userDimDfBroadcast.value)
.WithColumnRename(“用户ID”、“用户ID\u用户ID”)
.WithColumnRename(“用户ID”、“用户ID\U国家ID”)
.as(“userdim”)
,userAndRetailDates(“USER\u ID”)$“userdim.USER\u DIM\u USER\u ID”
&&UserAndDetailDates(“用户\u CNTRY\u ID”)$“userdim.USER\u DIM\u COUNTRY\u ID”
“内部”)
userandretaildates和userdim.show()
谢谢,
Prasad。

这里没有太多的内容(即使您的数据或列/表名称是机密的,查看一些代码可能会有用,这些代码可以显示您正在尝试实现的目标),但是
CartesianProduct
肯定是个问题。O(N^2)在大型数据集上,这是您真正想要避免的,在这种特殊情况下,它会触及Spark中的所有弱点

一般来说,如果联接扩展为显式笛卡尔积或等效运算,则表示联接表达式不是基于相等的,因此无法使用基于洗牌(或广播+哈希)的联接(
SortMergeJoin
HashJoin
)进行优化

编辑

在您的情况下,以下情况最有可能是问题:

userDf("CAL_DT") between(
  $"retailDates.WEEK_BEGIN_DATE",  $"retailDates.WEEK_END_DATE")
例如,最好在
userDf
上计算
WEEK\u BEGIN\u DATE
,然后直接加入

$"userDf.WEEK_BEGIN_DATE" === $"retailDates.WEEK_BEGIN_DATE"
另一个小的改进是在不使用UDF的情况下解析日期,例如使用
unix\u timestamp
函数

编辑


这里的另一个问题,由指出的是,
在Spark中没有太多的内容(即使您的数据或列/表名是机密的,查看一些代码可能会有用,这些代码可以显示您试图实现的目标),但是
CartesianProduct
肯定是一个问题。O(N^2)在大型数据集上,这是您真正想要避免的,在这种特殊情况下,它会触及Spark中的所有弱点

一般来说,如果联接扩展为显式笛卡尔积或等效运算,则表示联接表达式不是基于相等的,因此无法使用基于洗牌(或广播+哈希)的联接(
SortMergeJoin
HashJoin
)进行优化

编辑

在您的情况下,以下情况最有可能是问题:

userDf("CAL_DT") between(
  $"retailDates.WEEK_BEGIN_DATE",  $"retailDates.WEEK_END_DATE")
例如,最好在
userDf
上计算
WEEK\u BEGIN\u DATE
,然后直接加入

$"userDf.WEEK_BEGIN_DATE" === $"retailDates.WEEK_BEGIN_DATE"
另一个小的改进是在不使用UDF的情况下解析日期,例如使用
unix\u timestamp
函数

编辑

这里的另一个问题是Spark中的