我在AWS上的Athena数据库上有一个较大的数据集。我想同时阅读它,并且我已经习惯了foreach
包裹在R内分叉的方法。
我正在使用RJDBC
这是我正在尝试的内容:
out <- foreach(i = 1:length(fipsvec), .combine = rbind, .errorhandling = "remove") %dopar% {
coni <- dbConnect(driver, "jdbc:awsathena://<<location>>/",
s3_staging_dir="my_directory",
user="...",
password="...")
print(paste0("starting ", i))
sqlstring <- paste0("SELECT ",
"My_query_body"
fipsvec[i]
)
row <- fetch(dbSendQuery(coni, sqlstring), -1, block = 999)
print(i)
dbDisconnect(coni)
rm(coni)
gc()
return(row)
}
(对不起,我无法重现这一点 - 显然我无法在线分发数据库的密钥。)
当我运行它时,第一个c = number of cores
步骤运行正常,但它会挂起并且什么也不做 - 就我所知无限期而言。 htop
显示任何核心都没有活动。当我将for循环更改为仅循环c
个条目时,输出就是我所期望的。当我从并行更改为串行(%do%
而不是%dopar%
)时,它也可以正常工作。
这是否与连接未正确关闭或以某种方式被冗余定义有关?我已将连接放在并行循环中,因此每个核心应在其自己的环境中拥有自己的连接。但我对数据库知之甚少,无法确定这是否足够明显。
我很感激能够帮助我理解这里发生的事情的答案 - 此时此刻对我来说都是巫术。
答案 0 :(得分:0)
您是否将RJDBC
包(及其依赖关系 - methods
,DBI
和rJava
)传递到群集中的任何位置?
如果没有,您的代码的第一行应如下所示:
results <- foreach(i = 1:length(fipsvec),
.combine = rbind,
.errorhandling = "remove",
.packages=c('methods','DBI','rJava','RJDBC')) %dopar% {
我怀疑(但不知道)的一件事可能会让事情变得更加毛躁,因为RJDBC使用JVM来执行查询。不太了解rJava如何处理JVM初始化,以及每个线程是否可能尝试同时重用同一个JVM,或者他们是否有足够的外部环境信息来正确初始化一个JVM。
如果上述方法无效,则可以采取另一个问题排查步骤,将driver
的分配步骤移至%dopar%
环境。
在另一首曲目中,结果集中有多少行?如果结果集在百万+行范围内并且可以通过单个查询返回,我实际上在RJDBC
包中遇到了优化的机会,并在github上有一个打开的拉取请求(https://github.com/s-u/RJDBC/pull/50)我没有听过任何声音,但已经使用了几个月。在pull请求中记录了一个基本的基准测试,我发现在我运行的特定查询中,加速是非常重要的。
如果它似乎适用,您可以使用以下命令安装分支:
library(devtools)
devtools::install_github("msummersgill/RJDBC",ref = "harmonize", force = TRUE)