6

遠く離れた業界強度のデータベースに対して多くのSQLクエリを実行しますが、結果を受け取るまでに長い時間がかかります。Rを搭載したコンピューターがデータベースのほぼ隣にあると、はるかに高速になりました。これにより、コンピューターとデータベースの間の遅延がボトルネックになり、並列クエリを実行すると処理が高速化される可能性があると考えられます。私たちはさまざまな大陸にいます。

並列ではない動作バージョンは次のとおりです。

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ライブラリが利用できないようで、CRANで読んだことからわかるように、並列化のために以前のパッケージが並列に置き換えられています(「パッケージ」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のすべての貢献者に感謝します!

/クリス

更新: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を一緒に活用します。つまり、一度に1つのクエリを実行するだけで、データ転送中はCPUがほとんど使用されなくなり、CPUが動作している間はリンクが静かになります。並列クエリでは、データの到着とCPUが同時に動作しているのがわかります。全体として、それははるかに速くなりました。どうもありがとう!

/クリス

4

1 に答える 1

7

私のコメントで述べたように、このテクニックはおそらく速くはないでしょう。あなたの質問に答えるために、foreachパッケージはあなたのバージョンのRで利用可能です。おそらく、選択したリポジトリはまだ更新されていません。これを試して:

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

パッケージをインストールする必要があります。それでも問題が解決しない場合は、ここでOSのバイナリを取得し、メニューからインストールしてください。

ボトルネックがネットワーク接続である場合は、ネットワークに配置するものの量を減らすことによってのみ、プロセスを高速化できます。1つのアイデアは、データベースサーバーにリモート接続し、クエリを(サーバー上の)ファイルにダンプし、圧縮してからコンピューターにダウンロードし、Rで解凍してロードすることです。たくさんのように聞こえますが、おそらくR内でプロセス全体を実行できます。

更新のフォローアップでは、ステートメントに.packages引数が含まれていなかったようです。これが、関数の前に。foreachを付ける必要がある理由です。ループが必要とするパッケージを指定する必要があります。これは、ループが基本的にノードごとに新しいRセッションを開始し、各セッションをパッケージで初期化する必要があるためです。同様に、ループの外側にあるためアクセスできません。ループの内側に作成して、すべてのノードが独自のコピーを持つようにする必要があります。sqlQueryRODBC::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=''))
}

しかし、私が述べたように、これはおそらくこれ以上速くはないでしょう。

于 2012-05-15T16:15:48.657 に答える