2012-05-15 61 views
6

我在很远的地方对很多行业强度的数据库执行了许多SQL查询,但要花费很长时间才能收到结果。当我的计算机与R几乎在数据库的旁边时,速度要快得多,这导致我相信它是我的计算机和数据库之间的延迟是瓶颈,并且运行并行查询可能会加快速度。我们在不同的大陆。Windows中的并行for循环

这里是一个工作版本,是不是在并行:

doQueries <- function(filenameX, inp1, inp2) { 
    print(paste("Starting:", inp1, inp2, ",saving to", filenameX, sep=" ")) 
    # Here should the query be (using RODBC) 
    # save(queryresults, file="filenameX") 
} 

input.rows <- cbind(c("file1.rda","file2.rda","file3.rda"),c("A","B","C"),c(12,13,14)) 

for (i in 1:nrow(input.rows)) { 
    doQueries(filenameX=input.rows[i,1], inp1=input.rows[i,2], inp2=input.rows[i,3]) 
} 

我已经用下面的代码尝试,但在foreach库似乎并没有被avaliable,当我从阅读CRAN理解,并行将取代以前的软件包(“package'foreach'不可用(R版本2.15.0)”)。

library(parallel) 
library(foreach) 
foreach (i=1:nrow(input.rows)) %dopar% { 
    doQueries(filenameX=input.rows[i,1], inp1=input.rows[i,2], inp2=input.rows[i,3]) 
} 

我应该怎么做呢?

感谢所有对Stackoverflow的贡献者!

/Chris

更新:感谢nograpes,我设法加载库。下面的代码似乎工作:

library(RODBC) 
library(doParallel) 
library(foreach) 

# odbcCloseAll() 
# my_conn <- odbcConnect("database", uid="xx", pwd="yy", case="nochange") 

doQueries <- function(filenameX, inp1, inp2) { 
    print(paste("Starting:", inp1, inp2, ",saving to", filenameX, sep=" ")) 
    # sql.test <- RODBC::sqlQuery(my_conn, "SELECT * FROM zzz LIMIT 100", rows_at_time=1024) 
    # save(sql.test, file="filenameX") 
} 

input.rows <- cbind(c("file1.rda","file2.rda","file3.rda"),c("A","B","C"),c(12,13,14)) 

cl <- makeCluster(3) 
registerDoParallel(cl) 

foreach (i=1:nrow(input.rows)) %dopar% { 
    doQueries(filenameX=input.rows[i,1], inp1=input.rows[i,2], inp2=input.rows[i,3]) 
} 

stopCluster(cl) 

但是,当我有实际的SQL查询,出现此错误消息: 错误{: 任务1失败 - “第一个参数是不是一个开放的RODBC通道”

难道是这样,这在概念上将无法正常工作?该RODBC一次不能处理多个查询?

我非常感谢所有支持。

/克里斯

更新2:非常感谢nograpes了很好的和令人印象深刻的答案。很难判断数据传输本身是否更快(我认为总吞吐量快20%左右),但是我发现由于查询(大约100)有不同的响应时间,并且需要后处理(我将其包含在函数中在保存之前),我可以更好地利用链接和本地CPU。即只有一次查询时,CPU在数据传输过程中几乎不会被使用,然后在CPU工作时链路将保持安静。使用并行查询,我可以看到数据到达并且CPU同时工作。总的来说,它变得更快。非常感谢!

/Chris

+0

如果瓶颈是您的计算机和数据库之间的网络连接,则并行查询速度不会更快。 SQL查询将同时在数据库上执行(可能会更快一些,但可能不会),然后发送到您的计算机。发送到您的计算机部分将是缓慢的部分,你不会通过并行化来改变它。 – nograpes

回答

7

正如我在我的评论中提到的,这种技术可能不会更快。要回答你的问题,foreach包可用于你的R版本。也许你选择的版本库还没有更新。试试这个:

install.packages('foreach', repos='http://cran.us.r-project.org') 

应该安装包装。如果这不起作用,请为您的操作系统here获取二进制文件,然后通过菜单进行安装。

如果瓶颈是网络连接,那么您只能通过减少放入网络的东西来加速进程。一个想法是远程连接到数据库服务器,让它将查询转储到文件(在服务器上),压缩它,然后将其下载到您的计算机,然后让R解压缩并加载它。听起来好像很多,但是你可以在R内完成整个过程。

跟着你的更新,看起来你没有在你的foreach声明中加入.packages参数。这就是为什么你必须在sqlQuery函数前加上RODBC::。有必要指定循环所需的包,因为我认为它实际上为每个节点启动一个新的R会话,并且每个会话都需要使用包进行初始化。同样,你不能访问my_conn,因为它在循环之外,你需要在循环内创建,所以每个节点都有自己的副本。

library(RODBC) 
library(foreach) 
library(doParallel) 
setwd('C:/Users/x/Desktop') 

doQueries <- function(filenameX) { 
    sql.text<-sqlQuery(my_conn, 'SELECT * FROM table;') 
    save(sql.text, file=filenameX) 
} 

cl <- makeCluster(2) 
registerDoParallel(cl) 

foreach (i=1:2, .packages='RODBC') %dopar% { 
    my_conn <- odbcConnect("db", uid="user", pwd="pass") 
    doQueries(filenameX=paste('file_',i,sep='')) 
} 

但是,就像我提到的,这可能不会更快。

+0

让我知道它是否更快。 – nograpes

+0

是的,我很惊讶地看到更好的总利用率,请参阅上面的“更新2”。非常感谢! – Chris