有休消化#2

転職に伴い引っ越しをするので大掃除中です*1。引っ越し屋さんにはiMacのことを「テレビ」と伝えました。

まとまった時間がとれないので、休憩の合間にCouchDBとMongoDBの比較を試みます。自分用のメモです。

MongoDBを一切触ってない&CouchDBは十分すぎるほど触った上での比較なので、偏るかもしれません。あと浅いです。突っ込み大歓迎。あとまとまったらCouchDB-JPのほうに移します。

*1:今でも通えない距離じゃないのでお金は出ないと思うけど、気分転換重要。

CouchDB と MongoDB の比較 #1 通信プロトコル

まずは、DBを利用するにあたって、どんな環境が必要なの?ということで、プロトコルについて比べます。

項目 CouchDB MongoDB
通信プロトコル HTTP 専用プロトコル
利用環境 HTTP クライアントが使える環境 各種ドライバあり

いきなり比較が難しいですね。

CouchDBは、HTTP なので curl で確認できます。手軽に確認できる反面、オーバーヘッドはそれなりにあります。究極のパフォーマンスを求めるなら、Hovercraftというストレージを直接操作できるErlangライブラリを使った方がいいです。また、普通に使う場合でも couch-rest (Ruby/Gem) や couchdb-python (Python) などのドライバライブラリを使うという手もあります。

MongoDB のほうはBSON(http://www.mongodb.org/display/DOCS/BSON)という、JSONのようなものをバイナリでシリアライズしたデータをやりとりする専用プロトコルです。これだとちょっと取っつきにくそうですが、各種ドライバがあるのでドライバのAPIを覚えていけば大変ではないように見えます。

CouchDB と MongoDB の比較 #2 取り扱い可能なデータ

項目 CouchDB MongoDB
データタイプ null,bool,number,string,array,object(, binary) たくさん

これまた、Mongoのほうがよさげ。

CouchDBJSONなのでJSONで規定されるデータタイプに準じます。ただし、添付ファイル機能があるので、binary も(いろいろ制約がありますが)一応可能、ということで。Date がないのが致命的なので、書き込む際はDate型は"YYYY/MM/DD HH:MM:SS +ZZZZ"形式にシリアライズして、読み込むときは毎回 Date.parse() するなどの工夫が必要です。ドライバライブラリの中にはこのあたりをうまくやってくれるものもあるかと思います。

一方で、MongoDB では BSON でデータタイプを決めています。ドライバから利用するので、その言語のデータ型に適当にマップしてくれるものと想像ができます。で、http://www.mongodb.org/display/DOCS/BSON#BSON-ElementDataTypes を見る限り、JSONよりも表現が豊富です。Date もあるし。Timestamp もあるので、ドキュメント管理には向いているじゃないか。。。

CouchDB と MongoDB の比較 #3 ドキュメントで予約されたフィールド

CouchDBもMongoDBも、それぞれのドキュメントに対して一意キーである_idフィールドを持つようです。いずれも、ドキュメントの追加時に自動的にサーバー側で(UUID 32文字)付与させるか、クライアントから指定することができるようです(TODO: Mongo でもクライアントから指定できるかどうかは未検証)。

一方、CouchDBでは、_rev というドキュメントの衝突管理のための版番号を持ちます。版番号はドキュメントの更新履歴に対して一意のため、

  1. ドキュメントを取得
  2. 変更を実施
  3. ドキュメントを更新

の操作において、1の後、3をコミットする前に、他のクライアントによってドキュメントが更新されてしまった場合には、3. で送信する_revとDB上の_revが不一致のため、更新に失敗する、という仕組みを提供します。Optimistic Lockです。

一方で、MongoDBは「指定した条件にマッチしたドキュメントを更新する」というAPIを持っているので、_rev のような仕組みがなくても、同様のことは実施できます。これについては、「Atomic Operations」に記載があるようです。"Update if Current" の項が参考になります。

まとめます。

項目 CouchDB MongoDB
ドキュメントの一意性 _id で保証 _id で保証
更新衝突検出 _rev を使ったOptimistic Lock なし /「指定した条件にマッチしたドキュメントを更新する」ことでOptimistic Lockが実現できる

_rev はレプリケーションの衝突検出にも使うので、これについてはあとでまた調べます。