2012-03-29 3 views
14

私は非常に長い時間(それぞれ〜30分)かかるRをスクリプトに6つのSQLクエリがあります。各クエリが返すと、いくつかの標準レポートのデータを操作します。私がやりたいのは何RのSQLクエリを並列化するR

は、Oracle DBとWindowsマシン上でR.

私はから並列にこれらのSQL要求を実行するために、私のマルチコアのマシンを使用しています。私はblog postを使ってdoSNOWとforeachを使ってこれらのリクエストを分割しました。これが私がstackoverflowにある最良のものです。

私は、foreachのパラレル%do%バージョンでは動作するようにプロセスを取得できましたが、%dopar%では動作しませんでした。 %dopar%では空のセットを返します。以下は、テーブルを設定してクエリを実行するコードで、何が起こるかを見ることができます。あまりにも多くの基本コードがある場合は、事前にお詫び申し上げます。

私はいくつかの他のRパッケージを見てきましたが、明らかな解決策は見当たりませんでした。このようなプロセスを管理するためのよりよい方法があれば、それを聞いてみたいと思います。私はコンピュータ科学者ではなくアナリストです。ありがとう!

#Creating a cluster 
library(doSNOW) 
cl <- makeCluster(c("localhost","localhost"), type = "SOCK") 
registerDoSNOW(cl) 

#Connecting to database through RODBC 
ch=odbcConnect("",pwd = "xxxxx", believeNRows=FALSE) 
#Test connection 
odbcGetInfo(ch) 

#Creating database tables for example purposes 
qryA1 <- "create table temptable(test int)" 
qryA2 <- "insert into temptable(test) values((1))" 
qryA3 <- "select * from temptable" 
qryA4 <- "drop table temptable" 
qryB1 <- "create table temptable2(test int)" 
qryB2 <- "insert into temptable2(test) values((2))" 
qryB3 <- "select * from temptable2" 
qryB4 <- "drop table temptable2" 

sqlQuery(ch, qryA1) 
sqlQuery(ch, qryA2) 
doesItWork <- sqlQuery(ch, qryA3) 
doesItWork 
sqlQuery(ch, qryB1) 
sqlQuery(ch, qryB2) 
doesItWork <- sqlQuery(ch, qryB3) 
doesItWork 

result = c() 
output = c() 
databases <- list('temptable','temptable2') 


#Non-parallel version of foreach 
system.time(
foreach(i = 1:2)%do%{ 
result<-sqlQuery(ch,paste('SELECT * FROM ',databases[i])) 
output[i] = result 
} 
) 

output 

#Parallel version of foreach 

outputPar = c() 

system.time(
foreach(i = 1:2)%dopar%{ 
#Connecting to database through RODBC 
ch=odbcConnect(dsn ,pwd = "xxxxxx", believeNRows=FALSE) 
#Test connection 
odbcGetInfo(ch) 
result<-sqlQuery(ch,paste('SELECT * FROM ',databases[i])) 
outputPar[i] = result 
} 
) 

outputPar 

sqlQuery(ch, qryA4) 
sqlQuery(ch, qryB4) 
+2

は、ボトルネックの原因となっているものに応じて、プロセスが遅くすることができます。ボトルネックは、マシン上で実行されているRインスタンス(データベース、ネットワーク接続、データベースが稼動しているマシンなどではない)であることは確かですか? –

+0

'RODBC'パッケージはクラスタノードにロードされていますか?そうでなければ、あなたの 'foreach()'呼び出しに '.packages =" RODBC "'を追加してください。 – BenBarnes

+0

@Joshua Ulrich - 市販のOracle製品であるため、データベースはかなり堅牢です。クエリは、データベース内で多くの処理を必要とする複数のテーブルにまたがって結合するだけです。 SQL Developerからいくつかのインスタンスを開始するのが手作業ですが、Rスクリプトは私のために多くのポスト・クエリー処理を行いますので、複数の問合せを一度に開始するようにして、最長時間すべてのクエリ時間を一緒に追加するのではなく、長いクエリ時間を待たなければなりません。 –

答えて

9

あなたはシリアルforeachループ内で割り当てoutputPar[i] = resultを行うと、これは(実際のforeachの使用目的ではなく)OKです。並列ループでこの割り当てを行うと、OKではありません。 RevolutionのDavid Smithが答えた同様の質問については、http://tolstoy.newcastle.edu.au/R/e10/help/10/04/3237.htmlを参照してください。溶液として

、並行してデータベースに問い合わせる

system.time(
    outputPar <- foreach(i = 1:2, .packages="RODBC")%dopar%{ 
#Connecting to database through RODBC 
    ch=odbcConnect(dsn ,pwd = "xxxxxx", believeNRows=FALSE) 
#Test connection 
    odbcGetInfo(ch) 
    result<-sqlQuery(ch,paste('SELECT * FROM ',databases[i])) 
    result 
} 
) 
+1

非常にいいです - 私はこのように%dopar%コードを修正しました。すべての助けをいただきありがとうございます。 "test < - foreach(i = 1:2、.packages =" RODBC ")%dopar%{ #RODBCを介したデータベースへの接続 ch = odbcConnect(dsn、pwd =" xxxxxxx "、believeNRows = FALSE) #Test接続odbcGetInfo(CH) のSQLQuery(CH、ペースト( 'SELECT * FROM'、データベース[I])) }) test' –