通过R从Athena(AWS)数据库并行读取

时间:2017-10-04 15:10:03

标签: r amazon-web-services jdbc parallel-processing amazon-athena

我在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%)时,它也可以正常工作。

这是否与连接未正确关闭或以某种方式被冗余定义有关?我已将连接放在并行循环中,因此每个核心应在其自己的环境中拥有自己的连接。但我对数据库知之甚少,无法确定这是否足够明显。

我很感激能够帮助我理解这里发生的事情的答案 - 此时此刻对我来说都是巫术。

1 个答案:

答案 0 :(得分:0)

您是否将RJDBC包(及其依赖关系 - methodsDBIrJava)传递到群集中的任何位置?

如果没有,您的代码的第一行应如下所示:

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)