使用SparkyR在R中创建Lazy Spark读写拼花地板作业
我想创建一个spark作业,它从sql源读取数据(使用“spark\u read\u jdbc”),然后将结果写入拼花文件(“spark\u write\u parquet”) 对于sql语句中的小增量,需要多次执行此操作。我希望创建的工作是懒惰的,以便多个执行人可以拿起工作。以下是一些示例玩具代码:使用SparkyR在R中创建Lazy Spark读写拼花地板作业,r,apache-spark,dplyr,sparkr,sparklyr,R,Apache Spark,Dplyr,Sparkr,Sparklyr,我想创建一个spark作业,它从sql源读取数据(使用“spark\u read\u jdbc”),然后将结果写入拼花文件(“spark\u write\u parquet”) 对于sql语句中的小增量,需要多次执行此操作。我希望创建的工作是懒惰的,以便多个执行人可以拿起工作。以下是一些示例玩具代码: sql = "SELECT * FROM TBL_%s" for(i in seq(1,10)){ sql_to_read = sprintf(sql, i) optionSet$dbta
sql = "SELECT * FROM TBL_%s"
for(i in seq(1,10)){
sql_to_read = sprintf(sql, i)
optionSet$dbtable = paste0("(", sql_to_read ,") foo")
TEMP = spark_read_jdbc(sc, "TEMP", options = optionSet, memory = FALSE)
TEMP = TEMP %>% mutate(id := i)
TEMP %>% spark_write_parquet(., path = "/TEMP.parquet", mode = "append", partition_by = id)
}
问题是写入操作不能在强制串行操作的情况下延迟执行。有没有一种方法可以编写此代码,这样就可以简单地为整个操作创建一个spark作业,然后当我触发一个“collect”语句时,多个执行器将执行该操作?您可以始终使用代码的结构来完全避免该问题。因为所有写入都使用相同的输出表,所以可以将输入定义为单个联合:
xs <- 1:10
query <- glue::glue("SELECT {xs} AS _id, * FROM TBL_{xs}") %>%
glue::collapse(" UNION ALL \n")
xs在scala中使用线程解决了一个类似的问题:为什么不使用外部编排?这看起来像是可以通过气流来完成的,例如,只需传递参数数组。也就是说,为了能够在需要线程的时候提交多个作业,R没有本机多线程。将其委托给JVM应该是完全可能的,但老实说,这看起来很麻烦。您还可以在单独的流程中为每个作业建立新的连接。最好将所有内容都保存在单个环境中。spark的目的是分布处理(跨本地执行器或机器集群),因此从设计上讲,它是一种并行体系结构。奖品是创建懒惰的spark\u write\u拼花工作,然后在设计完完整的工作后将其交给spark执行。这里没有冲突。像这样简单的Spark迁移只需一个操作符,几乎不需要代码,就可以轻松处理。无论如何,我想这里要传达的信息是——你可以做到,但是实现这样的行为至少需要在单线程R环境之外授权一部分处理。用正确的方法做这件事,特别是处理部分故障,需要做大量的工作。这不是我所期望的,但值得一个好的捕获奖励。
optionSet$dbtable <- glue::glue("({query}) tmp")
spark_read_jdbc(sc, "TEMP", options = optionSet, memory = FALSE) %>%
spark_write_parquet(., path = "/TEMP.parquet", mode = "append", partition_by = id)