RODBC 和 foreach

RODBC & foreach

我想使用 foreach 语法来查询本地存储的数据库。

我的代码是这样的:

h <- odbcDriverConnect(connection)

cl<-makeCluster(no_cores)
registerDoParallel(cl)

foreach(i = 1:dim(Table)[1], 
        .combine = rbind,
        .export = "h",
        .packages = "RODBC")  %dopar%  {
          cat(i,"\n")
          #h <- odbcDriverConnect(connection)
          sqlQuery(query)
        }

odbcCloseAll()
stopCluster(cl)

当我使用 %do% 而不是 %dopar% 时它工作正常,但是当我尝试使其平行时我得到这个错误:

Error in { : task 1 failed - "first argument is not an open RODBC channel" In addition: Warning message: In e$fun(obj, substitute(ex), parent.frame(), e$data) : already exporting variable(s): h

当我将 h 放在 foreach 循环中时它起作用了,但是我知道在每一步都创建连接,我想避免这种情况。有什么办法可以将该连接导出到 foreach(与使用其他变量的方式相同)?

您无法将数据库连接导出到工作人员,因为它们无法正确序列化和反序列化(因为它们包含诸如套接字连接之类的东西)。相反,您需要在 worker 上创建它们,但为了提高效率,您应该创建它们一次,然后在 foreach 循环中重复使用它们。

由于您使用的是 doParallel,您可以使用 clusterEvalQ:

初始化工作程序
clusterEvalQ(cl, {
  library(RODBC)
  connection <- "???"  # how are you setting this?
  h <- odbcDriverConnect(connection)
})

然后您可以在您的 foreach 循环中使用 h,只要您防止 foreach 从 auto-exporting h 到工作人员:

foreach(i = 1:dim(Table)[1],
        .combine = rbind,
        .noexport = "h",  # make sure h is *not* exported!
        .packages = "RODBC")  %dopar%  {
  cat(i, "\n")
  sqlQuery(h, query)
}

使用.noexport="h"很重要,否则好的h会被屏蔽,你会从RODBC得到一个错误。