web-dev-qa-db-ja.com

MongoDBとRethinkDBの一括挿入パフォーマンスの比較

これはここでの私の公式の最初の質問です。より良い市民になる方法を学ぶことができるように、私の投稿に対するあらゆる/すべての批判を歓迎しますSO市民。

それぞれのPythonクライアントライブラリを使用して、MongoDBまたはRethinkDBのいずれかに傾倒し、潜在的に大きな電子メールオプトアウトリストを格納するための非リレーショナルDBMSを検証しています。私のアプリケーションの問題点は一括挿入のパフォーマンスです、したがって、MongoDBコレクションとRethinkDBコレクションの両方に5,000のバッチで20,000レコードを挿入する2つのPythonスクリプトを設定しました。

MongoDB pythonスクリプトmongo_insert_test.py:

NUM_LINES = 20000
BATCH_SIZE = 5000

def insert_records():
    collection = mongo.recips
    i = 0
    batch_counter = 0
    batch = []
    while i <= NUM_LINES:
        i += 1
        recip = {
            'address': "test%d@test%d.com" % (i, i)
        }
        if batch_counter <= BATCH_SIZE:
            batch.append(recip)
            batch_counter += 1
        if (batch_counter == BATCH_SIZE) or i == NUM_LINES:
            collection.insert(batch)
            batch_counter = 0
            batch = []

if __name__ == '__main__':
    insert_records()

ほぼ同一のRethinkDB python script rethink_insert_test.py:

NUM_LINES = 20000
BATCH_SIZE = 5000

def insert_records():
    i = 0
    batch_counter = 0
    batch = []
    while i <= NUM_LINES:
        i += 1
        recip = {
            'address': "test%d@test%d.com" % (i, i)
        }
        if batch_counter <= BATCH_SIZE:
            batch.append(recip)
            batch_counter += 1
        if (batch_counter == BATCH_SIZE) or i == NUM_LINES:
            r.table('recip').insert(batch).run()
            batch_counter = 0
            batch = []

if __name__ == '__main__':
    insert_records()

私の開発環境では、MongoDBスクリプトは1秒以内に20,000レコードを挿入します。

$ time python mongo_insert_test.py 
real    0m0.618s
user    0m0.400s
sys     0m0.032s

同じ環境では、RethinkDBスクリプトのパフォーマンスははるかに遅く、2分以上で20,000レコードが挿入されます。

$ time python rethink_insert_test.py
real    2m2.502s
user    0m3.000s
sys     0m0.052s

これら2つのDBMSがどのように機能するかに関して、ここで何か大きなものが欠けていますか? RethinkDBがこのテストで非常に悪いパフォーマンスを示しているのはなぜですか?

私の開発マシンには、これらのテストに使用できるメモリが約1.2GBありました。

25
njyunis

RethinkDBは現在、サーバー上で一度に1つの挿入を実行することにより、バッチ挿入を実装しています。 Rethinkはすべてのレコードをディスクにフラッシュするため(安全性を第一に考えて設計されているため)、これはこのようなワークロードに非常に悪い影響を及ぼします。

これに対処するために2つのことを行っています。

  1. 一括挿入は、一度に1つの挿入を実行しないように、サーバーに一括挿入アルゴリズムを介して実装されます。
  2. 必要に応じて、耐久性の制約を緩和して、キャッシュメモリが高スループットの挿入を吸収できるようにするオプションを提供します(ディスクとの同期を頻繁に行わない代わりに)。

これは4〜12週間で完全に修正されます(これが必要な場合は、slava @ rethinkdb.com宛てにメールを送ってください。優先順位を付け直すことができるかどうかを確認します)。

関連するgithubの問題は次のとおりです。

https://github.com/rethinkdb/rethinkdb/issues/207

https://github.com/rethinkdb/rethinkdb/issues/314

お役に立てれば。サポートが必要な場合は、遠慮なくpingしてください。

47
coffeemug

Coffemugが投稿したものはさておき:

  1. 使用しているドライバーのバージョンとmongodbへの接続の構成方法によっては、これらの挿入がサーバーによって確認されない場合もあります。 Pythonドライバーの最新バージョンを使用している場合、これらの操作はサーバーからの受信確認を待機しているだけです(これは、データがメモリに書き込まれていることを意味するわけではありません)。私が言及していることの詳細については、 Mongodb書き込み懸念設定 を確認してください。

  2. rethinkdbの場合、インサートを並列化することで速度を上げることができます。基本的に、複数のプロセス/スレッドを実行する場合は、速度が上がるのがわかります。 Mongoの場合、ロックが関係しているため、並列処理は役に立ちません。

そうは言っても、RethinkDBは書き込みの速度を向上させる可能性があります。

PS:私はRethinkで働いていますが、上記の点は両方のシステムに関する私の偏りのない知識に基づいています。

6
Alex Popescu

ここのPymongo開発者-そうしない場合に備えて、最新のpymongoバージョンとMongoClientまたはMongoRepicaSetClientを使用していることを確認してください。そうすれば、書き込みが確認され、起動して忘れることはありません。 @Alexが言うように、それらはおそらくあなたが必要とするものになるでしょう。

私が持っている他の考慮事項は次のとおりです。これはデータベースの主なユースケースですか、それとも単なる主要な問題点ですか。決定を下す前に、他のデータパターン、データのクエリ、使いやすさ、および保守性を検討することをお勧めします。

4
Ross

アナロジーをご容赦ください-しかし、それは私の主張を明確にします。

貴重なものを金庫に閉じ込めるのにそれほど時間はかかりませんが、何千回もやります。代わりに銀行の金庫室に投稿した場合は、銀行への移動中に貴重品が安全でない時間を考慮してください。その小包はおそらく他の多くの小包と一緒に積み上げられるでしょう-志を同じくする預金者から。誰かがあなたの小包を開けて、それを他のものと積み重ねて安全な金庫に入れます。

その中には、ディスクへのデータの定期的なコミットと、ディスクへのデータのバッチ処理または遅延書き込みの違いがあります。これは、データの整合性の向上と書き込みパフォーマンスの向上の間のトレードオフです。データの損失がそれほど問題にならない場合は、ディスクへの同期の頻度を減らし、更新をバッチ処理または遅延書き込みすることはまったく問題ありません。間違った選択をすると、いつかお尻に噛み付くので、賢明に選択してください!

0
user924272