前回は脇道にそれてパスワードの設定を実施しました。今回はデータの書き込みのパフォーマンス測定を行いたいと思います。
Introduction
NpSQLの売りはデータの読み書きです。RDBMSが持つ柔軟な集計や検索をある程度犠牲にして得た特徴ですが、どの程度凄いのでしょうか。
大量のデータの読み書きのパフォーマンスを計測してみます。
環境は
1 | OS:Windows 10 Pro 64bit |
Explanation
Write Small Objects
下記のオブジェクトを1,000,000個書き込みます。
試行回数は3回で、平均値をとっています。
1 | public sealed class Data |
MongoDB上では、書き込みの結果、下記の数値が得られました。
1 | Data Size 51.0 mb |
オペレーション/オブジェクト数 | 1,000,000 |
---|---|
Drop | 228.5 ms |
Insert (One) | 132881.25 ms |
Insert (Many) | 131191.67 ms |
Select (Countだけ) | 11 ms |
OneとManyは、Insertに使うメソッドの違いです。単一のオブジェクトの挿入かIEnumrableの挿入かの違いです。
差はないも同然でしたが。
一応書き込みは0.1-0.2ms/個のようです。これは速いのか?
Write Large Objects
次は下記のオブジェクトを1,000,000個書き込みます。
1 | public sealed class LargeData |
試行回数は3回で、平均値をとっています。
byte[]のサイズは100,000です。少なくともGCが苦手とする85,000よりは大きくしました。
ですが、残念なことに、書き込み終わる前に OutOfMemoryException でサンプルプログラムが落ちました。
落ちた直後のデータベースは
1 | Data Size 100 gb |
となっていました。
(まぁこれは、InsertOneによる結果ですが)
恐ろしいマネージャー。
恐ろしいストレージ。
計測できないので、1桁落として、100,000個にします。
あと、データベースを一度全てリセットします。
が、これも落ちる。ちなみに落ちるのは、InsertMany メソッド。
ちょっとあれなので計算しました。
100,000(個)*100(kb)=9765MB
とすると、半分ならギリギリ大丈夫?
…ダメでした。25,000でようやくOKでしたが、それでもメモリは5GB近く確保したままでした。
でも、InsertOneなら1,000,000個挿入しても、7GBまで保持しました。なんで?
このテスト、すっごいHDDに負荷かかる(白目) ずっとHDD、100%なんだぜ?
オペレーション/オブジェクト数 | 25,000 | 1,000,000 |
---|---|---|
Drop | 235 ms | 246.3 ms |
Insert (One) | 16815 ms | 818100 ms |
Insert (Many) | 19671 ms | 計測不可 |
Select (Countだけ) | 14.67 ms | 計測不可 |
参考値ですが、オブジェクト数とスピードは比例に近い感じですね。
あと、0.81ms/個のようです。こちらは単純にオブジェクトサイズには比例しないようですが。
Conclusion
予想以上に苦労しました。
まさかOutOfMemoryExpcetionで躓くとは予想外でした。
パフォーマンスとしては、あまり良いとも悪いとも言えないです。
どこかでRDMBSで似たデータ構造の比較試験がないでしょうか?
次は読み込みのパフォーマンス試験を予定です。
Source Code
テストに使った最終的なコードは下記になります。
https://github.com/takuya-takeuchi/Demo/tree/master/Database/MongoDB/MongoDB5