6

私が確信していること:

  • Linux で Java/Eclipse を使用しており、それぞれ 16/32 バイトの非常に多数のキーと値のペアをディスクに格納しようとしています。キーは完全にランダムで、SecureRandom で生成されます。
  • 速度は、約 100 万エントリに達するまで、約 50000 挿入/秒で一定です。
  • この制限に達すると、Java プロセスは 1 ~ 2 秒ごとに CPU 使用率が 0% から 100% まで、メモリが 150MB から 400MB まで、1 秒あたり 10 回の挿入から 100 回まで変動します。
  • Berkeley DB と Kyoto Cabinet の両方、および Btrees と Hashtables の両方で試しました。同じ結果です。

何が貢献するか:

  • SSDに書き込み中です。
  • 挿入ごとに、平均で 1.5 回の読み取りが行われ、常に読み取りと書き込みが交互に行われます。

キャッシュ/バッファの制限に達するまで、ナイスな 50000 レートが上昇していると思われます。次に、この質問で提案されているように、SSD が読み取り/書き込みを混在させて処理しないことが原因で、大幅な速度低下が発生する可能性があります: Low-latency Key-Value Store for SSD

質問:
この極端な速度低下はどこから来るのでしょうか? すべてが SSD のせいではありません。多くの人がSSDを快く高速なDB処理に使用しており、読み取りと書き込みが混在していると思います。

ありがとう。

編集:メモリ制限を確実に削除しました。Javaプロセスには、より多くのメモリを割り当てる余地が常にあります。
編集:読み取り値を削除して挿入のみを行っても、問題は変わりません。

最終編集 :レコードの場合、ハッシュ テーブルの場合は、初期番号バケットに関連しているようです。京都のキャビネットでは、その数は変更できず、デフォルトで 100 万以下に設定されているため、作成時に適切な数を取得することをお勧めします (保存するレコードの最大数の 1 から 4 倍)。BDB の場合、バケットの数を徐々に増やすように設計されていますが、リソースを消費するため、事前に数を定義しておくことをお勧めします。

4

1 に答える 1

4

問題は、使用しているデータベースの強力な耐久性の保証に関連している可能性があります。

基本的に、ACIDに準拠しているデータベースの場合、データベースのコミットごとに少なくとも1つのfsync()呼び出しが必要になります。これは、耐久性を保証するために発生する必要があります(そうでない場合、システム障害が発生した場合に更新が失われる可能性があります)が、ディスク上のデータベースの内部整合性も保証します。データベースAPIは、fsync()呼び出しが完了する前に挿入操作から戻りません。

fsync()は、SSDであっても、多くのオペレーティングシステムやディスクハードウェアで非常に重い操作になる可能性があります。(例外は、バッテリーまたはコンデンサーでバックアップされたエンタープライズSSDです。キャッシュフラッシュ操作を基本的にノーオペレーションとして扱い、おそらく発生している遅延を正確に回避できます。)

解決策は、1つの大きなトランザクション内ですべてのストアを実行することです。Berkeley DBについてはわかりませんが、sqliteの場合、この方法でパフォーマンスを大幅に向上させることができます。

それが問題であるかどうかを判断するには、straceを使用してデータベースの書き込みプロセスを監視し、頻繁なfsync()呼び出しを探すことができます(毎秒数回以上はかなり強力なヒントになります)。

更新:耐久性 が絶対に必要ないことが確実な場合はBerkeleyDBでのPutPerformanceの最適化の回答を試すことができます。その場合は、Berkeley DBのTDS(トランザクションデータストレージ)機能を調べる必要があります。

于 2012-10-23T12:58:03.573 に答える