2012-05-15 59 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