使用R doParallel或foreach从mysql并行获取数据

时间:2016-04-21 03:26:56

标签: mysql r foreach parallel-processing doparallel

我正在尝试使用R从MySQL数据库并行获取数据。以下代码逐个获取数据并正常工作。但我希望通过发送多个查询并将其保存到不同的变量来加快进程。稍后我会在变量中合并时间序列。

library(RMySQL)
dbConnect(MySQL(), user='external', password='xxxxxxx', dbname='GMT_Minute_Data', host='xx.xx.xxx.xxx')

sqlData <-select TradeTime, Open, High, Low, Close from ad where tradetime between ‘2014-01-01’ and ‘2015-10-20’
data1= dbFetch(sqlData, n=-1)
sqlData <-select TradeTime, Open, High, Low, Close from ty where tradetime between ‘2014-01-01’ and ‘2015-10-20’
data2 = dbFetch(sqlData, n=-1)
sqlData <-select TradeTime, Open, High, Low, Close from ax where tradetime between ‘2014-01-01’ and ‘2015-10-20’
data3 = dbFetch(sqlData, n=-1)

connections <- dbListConnections(MySQL())
for(i in connections) {dbDisconnect(i)}

我尝试使用以下代码并行获取数据:

library(foreach)
library(doParallel)
library(RMySQL)

fetchData<- function(nInst, inst1, inst2, inst3, inst4, inst5, startDate, endDate, con1){

  inst<-NULL
  sqlData <-NULL

  if(nInst==1)
    inst<-inst1
  else if(nInst==2)
    inst<-inst2
  else if(nInst==3)
    inst<-inst3
  else if(nInst==4)
    inst<-inst4
  else if(nInst==5)
    inst<-inst5

  sqlData <- dbSendQuery(con1, paste0('select TradeTime, Open, High, Low, Close from ', inst, ' where tradetime between \'',  startDate, '\' and \'',  endDate, '\'' ))
  data1 = dbFetch(sqlData, n=-1)
  print(head(data1))

  data1 
}

cluster = makeCluster(5, type = "SOCK")
registerDoParallel(cluster)
mydb <- NULL
clusterEvalQ(cluster, {

  mydb <- dbConnect(MySQL(), user='external', password='xxxxxx', dbname='GMT_Minute_Data', host='xx.xx.xxx.xxx')
  NULL
})


allDataList<-foreach(n =1:2, .verbose=TRUE, .packages=('RMySQL')) %dopar% {
  fetchData(n, inst1, inst2, inst3, inst4, inst5, startDate, endDate, mydb)

}
stopCluster(cluster)
on.exit(dbDisconnect(mydb))

有时代码只提取第一台乐器的数据,而不是其他乐器的数据。

如果有人知道解决方案,请提供帮助。

谢谢,

1 个答案:

答案 0 :(得分:0)

我认为问题在于foreach会将mydb变量自动导出给工作人员,从而无法用clusterEvalQ初始化它。数据库连接无法序列化并正确发送到其他计算机,这就是使用clusterEvalQ手动初始化数据库连接的原因。通过foreach .verbose=TRUE选项,您可以验证mydb 是否已自动导出。如果它说它是自动导出的,你需要阻止它。

在您的示例中,您可以通过简单地删除mydb语句来阻止mydb <- NULL自动导出,但我建议您使用foreach .noexport='mydb'选项来确定它是从不自动导出。这是一个精简的例子:

library(doParallel)

fetchData <- function(ignore) {
  mydb
}

cluster <- makeCluster(5, type = "SOCK")
registerDoParallel(cluster)

clusterEvalQ(cluster, {
  mydb <- sample(100, 1) # different value for each worker
  NULL
})

r <- foreach(n=1:2, .noexport='mydb', .verbose=TRUE) %dopar% { 
  fetchData(n)
}

在这种情况下,foreach会分析fetchData函数并注意到它正在使用名为mydb的变量。因此,如果在主服务器上定义了mydb,它将自动导出它,除非您告诉它不要。这就是为什么我建议使用.noexport='mydb',即使它没有在本地环境中定义。它确保您的函数不会使用损坏的数据库连接。