2012-12-20 14 views
6

私はrmongodbを使用して、特定のコレクション内のすべてのドキュメントを取得しています。それは動作しますが、私は何百万もの小さな文書を扱っています。潜在的に100M以上です。これは、結果の数百または数千のために正常に動作しますが、ループは非常に非常に遅いながらというrmongodbを使用して大きな結果セットを高速化

count <- mongo.count(mongo, ns, query) 
cursor <- mongo.find(mongo, query) 
name <- vector("character", count) 
age <- vector("numeric", count) 
i <- 1 
while (mongo.cursor.next(cursor)) { 
    b <- mongo.cursor.value(cursor) 
    name[i] <- mongo.bson.value(b, "name") 
    age[i] <- mongo.bson.value(b, "age") 
    i <- i + 1 
} 
df <- as.data.frame(list(name=name, age=age)) 

をcnub.org/rmongodb.ashx:私は、ウェブサイト上の著者によって提案された方法を使用しています。これをスピードアップする方法はありますか?多分マルチプロセッシングの機会でしょうか?任意の提案をいただければ幸いです。私は1時間に1Mを平均しており、この速度ではデータフレームを構築するのに1週間しかかかりません。

編集: 私は、whileループのベクトルが多いほど遅くなることに気付きました。私は今、各ベクトルごとに別々にループしようとしています。しかし、まだハックのように思えますが、より良い方法が必要です。

編集2: 私はdata.tableで運が少しあります。 ITSは、まだ実行されているが、それはそれは進行中だが、はるかに理想的な

dt <- data.table(uri=rep("NA",count), 
       time=rep(0,count), 
       action=rep("NA",count), 
       bytes=rep(0,count), 
       dur=rep(0,count)) 

while (mongo.cursor.next(cursor)) { 
    b <- mongo.cursor.value(cursor) 
    set(dt, i, 1L, mongo.bson.value(b, "cache")) 
    set(dt, i, 2L, mongo.bson.value(b, "path")) 
    set(dt, i, 3L, mongo.bson.value(b, "time")) 
    set(dt, i, 4L, mongo.bson.value(b, "bytes")) 
    set(dt, i, 5L, mongo.bson.value(b, "elaps")) 

}

+0

私はプログラマーではありませんが、実際には使用したことはありませんが、コレクション全体を反復処理して検証を実行するのではなく、必要なデータの部分集合を選択するのはなぜですか?この場合、ただ1つではなく6つのカーソルをサーバー側のように送信する方が簡単です。 – Sammaye

+0

?もちろん、whileループのベクトルが増えるほど遅くなります。もっとやるべきことがあります。だから時間がかかります。それとも非線形ですか?どのようにループしているものの数の異なる値で動作しますか?または、「より多くのベクトル」によって、年齢や名前などのより多くのものを意味するのでしょうか?定かでない。 – Spacedman

+0

@Sammaye、まさに私が各ベクトルごとに別々にループすることを意味するものです。私はその昨夜、そのループにカウンタを入れて、それはちょうど死亡したように見えた、それは数時間後に印刷を停止しました。放棄はちょうどぶら下がっている。だからこの方法は役に立たなかった。 – rjb101

答えて

3

からあなたはmongo.find.exhaustオプションをしようとする場合があり、4時間後に(これは私の現在のテスト・セットである)12Mを終了しますように見えます

cursor <- mongo.find(mongo, query, options=[mongo.find.exhaust]) 

これは実際に使用するケースで最も簡単な修正方法です。

ただし、rmongodbドライバには、他のドライバで利用できるいくつかの追加機能がありません。たとえば、JavaScriptドライバにはCursor.toArrayメソッドがあります。すべての検索結果を配列に直接ダンプします。 Rドライバにはmongo.bson.to.listの機能がありますが、おそらくmongo.cursor.to.listが必要です。ドライバーの開発者にアドバイスを求めてもらう価値があります。

ハックリの解決策は、ドキュメントがそれぞれ100,000個の元のドキュメントのデータ "チャンク"である新しいコレクションを作成することです。そしてこれらのそれぞれはmongo.bson.to.listで効率的に読み取ることができます。チャンクされたコレクションは、mongoサーバーのMapReduce機能を使用して構築できます。

+0

mongo.find.exhaustがどのように速度を改善するかについての説明を見つけてください。それが実際にどのように機能するか知っていますか? – user1176316

+0

私の理解が限られているのは、一度にすべてのクエリの一致を強制的に取得するということです。 cursor.nextからデータベースへの繰り返し呼び出しのオーバーヘッドが重要な場合は、速度を向上させることができます。私は、このユースケースで実際に助けてくれるのは3%のチャンスしか与えませんが、試してみるだけの簡単な変更です。私の最高の参考資料はhttp://mongodb.github.com/node-mongodb-native/api-generated/collection.html#find – mjhm

1

私はこれを一般的な方法で行うより早い方法がないことを知っています。あなたは外国のアプリケーションからデータをインポートしており、インタプリタ言語で作業しています。rmongodbがコレクション内の文書の構造を予測する方法はありません。このプロセスは、何千ものドキュメントを扱うときに本質的に遅くなります。

+1

ありがとうございます。ドキュメントはmongo.find.exhaustで一種の光ですが、詳しく説明できますか?私はこのオプションを追加し、Rはクラッシュしました。 – rjb101

+0

問題は毎回i = i + 1で追加されています。私はRがデータ構造をコピーするたびにそれを置き換えていると考えています。それが大きくなれば悪くなります。これは、Pythonのように、解釈された言語とは関係がありません。 –

関連する問題