0

私はAWSのAthenaデータベースで大規模なデータセットを持っています。ここで私がしようとしています何私は並行して、そこから読みたい、と私はRJDBCAWSのAthena(AWS)データベースからの並列読み込み、

を使用してい

R.

内からフォークに foreachパッケージのアプローチに慣れてる:

out <- foreach(i = 1:length(fipsvec), .combine = rbind, .errorhandling = "remove") %dopar% { 
    coni <- dbConnect(driver, "jdbc:awsathena://<<location>>/", 
      s3_staging_dir="my_directory", 
      user="...", 
      password="...") 
    print(paste0("starting ", i)) 
    sqlstring <- paste0("SELECT ", 
      "My_query_body" 
      fipsvec[i] 
    ) 
    row <- fetch(dbSendQuery(coni, sqlstring), -1, block = 999)   
    print(i) 
    dbDisconnect(coni) 
    rm(coni) 
    gc() 
    return(row) 
} 

(申し訳ありませんが、私はこれが再現することはできません - 。私は明らかにオンラインDBへの鍵を配ることはできません)

私はこれを実行すると、最初のc = number of coresのステップが細かい実行されますが、それがハングアップし、何もしない - indefi私が知る限り、ニティエリ。 htopはいずれのコアでも何の活動も示さない。そして、forループをcのエントリだけにループするように変更すると、出力が期待通りになります。私がパラレルからシリアルに変更すると(の代わりに%dopar%)、それはうまく動作します。

これは、接続が正しく閉じられていない、または何らかの形で重複して定義されていることと関連していますか?私は並列ループ内に接続を配置したので、各コアはそれぞれの環境で独自の接続を持つ必要があります。しかし、これが十分に明確であるかどうかを知るためにデータベースについて十分に知りません。

ここでは何が起こっているのかを理解するのに役立つ回答をいただければ幸いです。

答えて

0

RJDBCパッケージ(およびその依存関係 - methodsDBI、およびrJava)をどこのクラスタにも渡していますか?

されていない場合は、あなたのコードの最初の行は以下のようになります:私は疑う(しかし知らない)

results <- foreach(i = 1:length(fipsvec), 
        .combine = rbind, 
        .errorhandling = "remove", 
        .packages=c('methods','DBI','rJava','RJDBC')) %dopar% { 

一つのことは、物事を作るかもしれない少し毛深いがRJDBCが使用していることですクエリを実行するJVM rJavaがJVMの初期化を処理する方法や、各スレッドが同じJVMを同時に再利用しようとしているかどうか、または最初に適切に初期化するための外部環境についての十分な情報があるかどうかについては十分知識がありません。

上記の問題が解決しない場合の別のトラブルシューティング手順は、driverの割り当て手順を%dopar%環境に移動することです。

別のトラックでは、結果セットにいくつの行がありますか?結果セットが100万行以上の範囲にあり、単一のクエリで返すことができる場合、実際にはRJDBCパッケージ内の最適化の機会を得て、github(https://github.com/s-u/RJDBC/pull/50)のオープンプルリクエストを聞いたことがあります私は数ヶ月間自分自身を使ってきました。プルリクエストには基本的なベンチマークが記載されていますが、私が実行していた特定のクエリではスピードアップが相当であることがわかりました。

それが該当すると思われる場合は、とブランチをインストールすることができます:それは `.packages`引数ではありません

library(devtools)  
devtools::install_github("msummersgill/RJDBC",ref = "harmonize", force = TRUE) 
+0

。私の経験では、これはWindowsマシンでのみ重要です。そして、とにかく、4コアのインスタンスで4つのエントリをループすると、並列スクリプトがうまく動作します。したがって、各スレッドは1回のみの反復を実行できます。今のところドライバーを動かそうとしています... –

+0

もう1つの手順として、 '.jinit(force.init = TRUE)'行を%dopar%環境の最初の行に含めてください。 (しかし、私はこの時点で本当にちょうどボールを振っていますが、自分自身のJava側のロックをしっかりと理解していない) –

+0

ドライバーコールの内部を動かすことは役に立ちません。今すぐ 'harmonize'ブランチを試してみます - これを並行してやろうとしているのは、大きなチャンクをメモリに読み込もうとするとエラーが出るということです。私は約1e5行しか持っていませんが、私は3000列あり、それらのほとんどが必要です。 –

関連する問題