2017-01-31 40 views
0

我想使用foreach語法來查詢本地存儲的數據庫。RODBC&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) 

當我使用%做%,而不是%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(與其他變量一樣)?

+0

*我想使用foreach語法來查詢本地存儲的數據庫* ...爲什麼?你真正的問題是什麼?還是你在做這個學習? – Parfait

+0

我只需要得到一些不相互關聯的查詢結果,所以我期望這是一個非常平行的問題。我希望這樣我可以更快地獲得結果。我錯了嗎? 但是,即使它沒有讓速度更快,我想知道是否有可能在foreach中導出連接而不是變量 – Swistak

回答

0

您不能將數據庫連接導出到工作人員,因爲他們無法正確序列化和反序列化(因爲它們包含套接字連接等內容)。相反,您需要在工作人員上創建它們,但爲了提高效率,您應該創建一次,然後在您的foreach循環中反覆使用它們。

由於您使用doParallel,你可以用clusterEvalQ初始化工人:

clusterEvalQ(cl, { 
    library(RODBC) 
    connection <- "???" # how are you setting this? 
    h <- odbcDriverConnect(connection) 
}) 

然後可以使用h從您的foreach循環,只要你避免的foreach從汽車出口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得到一個錯誤。

+0

感謝它的工作!還有一個問題 - 我是否需要爲每個ODBC連接實例都有可用的RAM?對於較小的數據庫,它工作得更快,但是當我嘗試連接到更大的數據庫時,幾分鐘後CPU開始閒置,我認爲這可能與缺少RAM有關。 – Swistak

+0

@Swistak對不起,我對數據庫或ODBC並不瞭解。我建議您嘗試在計算機上運行進程監視工具(任務管理器?)以查看R會話是否使用了大量內存。 –

+0

@Stave謝謝,我試過了,不幸的是,由ODBC連接取得的內存不會在任務管理器中顯示爲R或甚至另一個進程的一部分(但是,當我關閉連接時,我可以看到內存使用顯着下降)。再次感謝您使用foreach包的幫助! – Swistak