2010年11月10日水曜日

MongoDBのCSVロード機能をSqlite3、PostgreSQLと比較してみた

DBMSにはCSV等の外部ファイルを一括ローディングする機能があるものがあります。今回はMongoDB,Sqlite3,PostgreSQLのCSVローディング機能を実行して速度を比較してみました。

0.CSVネタの準備
郵便番号のCSVがあったのでこれを使おうと思いましたが、思うところあって約50MBのデータを自作しました。1フィールド目=番号、2フィールド目=番号のSha1値という非常に簡単なもので、100万行分作成しました。(Pythonで作成してます)
↓こんな感じ…
------------------------------------------------
1,356a192b7913b04c54574d18c28d46e6395428ab
2,da4b9237bacccdf19c0760cab7aec4a8359010b0
3,77de68daecd823babbb58edb1c8e14d7106e83bb

999999,1f5523a8f535289b3401b29958d01b2966ed61d2
1000000,b27585828a675f5acfef052dd1a8cf0c6c1ee4b0
------------------------------------------------

↓Pythonで作成する際は以下のような感じで・・・
---------------------------------------------------
import hashlib

i=0
while i < 1000000:
 i += 1
 print str(i)+","+hashlib.sha1(str(i)).hexdigest()
---------------------------------------------------


尚、以下の確認は家のローカルPC(Dell製)で行いましたが、

CPU→ Celeron(R) Dual-Core CPU  T3000  @ 1.80GHz
OS→ Fedora13
です。



1.MongoDB

MongoDBにはmongoimportコマンドというものがあり、CSVファイルを一括ローディング可能です。以下のような形で実行しました。今回はtimeコマンドで時間を測定しています。

[user@user ~]$ time mongoimport -d test -c hash --dbpath /home/user/mongodata/ -f id,value --type csv --file /tmp/neta.csv

testデータベースのhashコレクションにid,valueというカラムを持ったneta.csvを格納します。結果は以下です。
----------------------
real    0m40.137s
user    0m30.579s
sys     0m8.410s
----------------------
何度か行いましたが、大体同じような結果になりました。
尚、他のデータでもやってみましたが、mongoimportコマンドは数字のみの値については全てnumber型?と解釈するようで、前に0が埋まっている数字を文字列としてローディングしようとしても前0は全てカットされました。また"--type CSV"を指定しないと、大量のエラーが出力されます。

※MongoDBのバージョンはv1.6.2です。


2.Sqlite3

.import コマンドによりCSVネタのローディングが可能です。
まず、TABLEを作成しました。
sqlite> create table hash ( id INTEGER PRIMARY KEY , value TEXT );

その後、
以下のコマンドでローディングを行います。
[user@user ~]$ time sqlite3 testdb ".import '/tmp/neta.csv' hash"
testdbのhashテーブルに対してneta.csvをローディングしました。
結果は以下の通りです。
----------------------
real    0m8.961s
user    0m6.609s
sys     0m0.949s
----------------------

すこしはまったのですが、sqlite3はデフォルトのDelimiterは"|"らしいのでCSVネタを
1|356a192b7913b04c54574d18c28d46e6395428ab
のように作成しなおしました。

※Sqlite3のバージョンは3.6.22です


3.PostgreSQL

COPYコマンドによりCSVの一括ローディングが出来ます。

まず、以下でテーブルを作ります。
testdb=# create table hash ( id integer PRIMERY KEY , value TEXT ) ;

その後、
COPY hash FROM '/tmp/neta.csv' DELIMITER '|' ;
と記載したファイル(copy.txt)を作成し、以下を実行します。

-bash-4.1$ time psql testdb -f /tmp/copy.txt
testdbに対してcopy.txtに記載してあるCOPYコマンドを実行しました。
結果は以下の通りです。
----------------------
real    0m12.746s
user    0m0.001s
sys     0m0.003s
----------------------

※PostgreSQLのバージョンは9.0です。


まとめ
Realだけで比較すると以下になります。
Mongodb…0m40.137s
Sqlite3…0m8.961s
Postgresql…0m12.746s

パフォーマンスが一番良いと勝手に考えていたMongoDBは実は一番悪いという結果になりました。もちろんこれだけでその製品のパフォーマンスを語る事は出来ませんが、少なくともCSVのローディング機能についてはSqlite3やPostgreSQLに軍配があがりました。

と言うか、MongoDB遅すぎっ!

これがMongoDBの構造的な問題なのか、まだまだ改善の余地があるのかは不明です。また、上記確認ですが、全てインストール時のデフォルトの状態で実施しており、何らかのパラメータをいじってチューニング、、、みたいな事は一切していません。