24

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

私は、潜在的に大規模な電子メール オプトアウト リストを格納するために非リレーショナル DBMS を精査しており、それぞれの Python クライアント ライブラリを使用して、MongoDB または RethinkDB に傾倒しています。私のアプリケーションの問題点は一括挿入のパフォーマンスです。そのため、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 スクリプト 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 ありました。

4

4 に答える 4

47

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してください。

于 2013-03-01T06:49:22.247 に答える
6

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

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

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

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

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

于 2013-03-01T07:55:23.213 に答える
4

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

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

于 2013-03-01T10:08:26.947 に答える
0

類推を許してください - しかし、それは私の主張を非常に明確にします。

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

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

于 2015-11-07T00:55:02.807 に答える