我的Spark应用程序如下:
1)使用Spark SQL在数据框“ dataDF”中执行大型查询
2)foreach分区涉及“ dataDF”:
2.1)获取关联的“已过滤”数据帧,以便仅使分区关联数据
2.2)对“过滤后的”数据帧进行特定工作并写入输出
代码如下:
val dataSQL = spark.sql("SELECT ...")
val dataDF = dataSQL.repartition($"partition")
for {
row <- dataDF.dropDuplicates("partition").collect
} yield {
val partition_str : String = row.getAs[String](0)
val filtered = dataDF.filter($"partition" .equalTo( lit( partition_str ) ) )
// ... on each partition, do work depending on the partition, and write result on HDFS
// Example :
if( partition_str == "category_A" ){
// do group by, do pivot, do mean, ...
val x = filtered
.groupBy("column1","column2")
...
// write final DF
x.write.parquet("some/path")
} else if( partition_str == "category_B" ) {
// select specific field and apply calculation on it
val y = filtered.select(...)
// write final DF
x.write.parquet("some/path")
} else if ( ... ) {
// other kind of calculation
// write results
} else {
// other kind of calculation
// write results
}
}
此类算法成功运行。 Spark SQL查询已完全分发。但是,对每个结果分区进行的特定工作是按顺序进行的,结果是无效的,尤其是因为与分区相关的每次写操作都是按顺序进行的。
在这种情况下,用并行/异步方式替换“ for yield”的方法是什么?
谢谢
答案 0 :(得分:0)
如果使用特定环境所需的特定逻辑写入Hadoop范围之外的数据存储,则可以使用foreachPartition。
其他地图等
.par并行集合(Scala)-谨慎使用。用于读取文件并对其进行预处理,否则可能会带来风险。
线程。
您需要检查正在执行的操作以及是否可以引用该操作,在foreachPartition块内使用wd等。您需要尝试一下,因为某些方面只能为驱动程序编写,然后才能分发给驱动程序。执行者通过SPARK给工人。但是,您不能按照以下方式为worker编写spark.sql-最后,由于某些格式化方面的错误,我刚在此处输入了文本块。请参阅发布结束。
在下面同样不能使用df.write或df.read。您可以做的是将单独的execute / mutate语句写入ORACLE,mySQL。
希望这会有所帮助。
rdd.foreachPartition(iter => {
while(iter.hasNext) {
val item = iter.next()
// do something
spark.sql("INSERT INTO tableX VALUES(2,7, 'CORN', 100, item)")
// do some other stuff
})
或
RDD.foreachPartition (records => {
val JDBCDriver = "com.mysql.jdbc.Driver" ...
...
connectionProperties.put("user", s"${jdbcUsername}")
connectionProperties.put("password", s"${jdbcPassword}")
val connection = DriverManager.getConnection(ConnectionURL, jdbcUsername, jdbcPassword)
...
val mutateStatement = connection.createStatement()
val queryStatement = connection.createStatement()
...
records.foreach (record => {
val val1 = record._1
val val2 = record._2
...
mutateStatement.execute (s"insert into sample (k,v) values(${val1}, ${nIterVal})")
})
}
)