なぜMongoDBなのか

25th Feb, 2010 | mongodb ruby rails

ここを見てもらってる人に、「MongoDBって何がいいの?」と改めて聞かれてしまって、ああ、そっか、そういうこと書いてなかったな、と思ったので、なぜ自分がMongoDBに興味を持っているのか、ということを書いてみた。いざ自分の思いを書いてみたらRails中心の話になってしまったけど、モダンなフレームワークならそんなに話は変わらないのかな、と思っている。


そもそものきっかけは、ここ半年間くらいRuby on Rails(以下RoR)で開発していることにある。

ここ半年弱ほどRoRで開発をして、それなりに満足しているのだけど、ActiveRecordに関しては色々とひっかかるところがあった。

「ActiveRecordがRoRの素晴らしいところそのものだ」と評価している人もいるが、自分の中では逆で、ActiveRecordはRoRの中でもかなりいまいちな部分。

いや、ActiveRecordというよりも、O/Rマッパーの限界なのかな。実際、ActiveRecordはO/Rマッパーの中では、いい方だと思う。今まで、自分用O/Rマッパーを作ったり、それなりの数のO/Rマッパーを見てきたけど、そういうのに比べても、確かにActiveRecordはよくできている。

でも、RoRがよくできたフレームワークなだけに、O/Rマッパー経由RDBMSを使うことに、色々な無駄を感じてしまう。

たとえば、1つのテーブルから同じ条件で検索し、複数のインスタンスを作るために、primary key(id)を検索条件として、何度も検索するとか。「そこはSQL一発で持ってこいよ」と思ってしまう。またそこからlazyに外部キーで他のModel(テーブル)のオブジェクトを持ってこようとすると、またprimary keyでの検索が走る。

一人のユーザが一つの画面を開くだけでSQLを何十回も発行することも普通に起こる。これはどう考えてもSQLの使い方として間違っている。SQLはそういう風に作られていないので、結局(RoR自体を含めた)アプリケーション側の別のレイヤーでインスタンスをCacheしたりと、どんどん複雑になっていく。

そういうのが嫌で、RDBMSとして正しく使おうと、find()で:includeとか:joinsとか使いだすと、今度はどんどんRoR(Ruby)のコードのSQL成分が増していく。全然楽しくない。

つまり、

  1. SQLっぽく書かずに、Ruby(ActiveRecord)っぽくきれいに書くように頑張る
  2. でも、ロジック的/パフォーマンス的に頑張るのが限界だった場合に、SQLっぽいコードをRubyに書くことになる
  3. そうこうしているうちにRubyらしい可読性の高いコードは消えSQLっぽいコードにまみれる

この流れにうんざりする。そもそも1.の段階でも脳内では普通にSQLのことを考えている。だったら最初からSQL書けよ、と思ってしまう。

結局、O/Rマッパーで、きれいに書けるところは、検索した結果でオブジェクトを作る、または、primary *key*指定で持ってきてそれを元にオブジェクトを作る。これだけ書けて、十分な性能が出るなら、RDBMSでなくても、(そこそこの機能を持った) Key Value Storageで十分なんじゃないのかな、とぼんやりと思っていた。

もう一つActiveRecordで嫌いなのが、Modelのコードにカラムの情報を持たない、というとこと。DRYのためだかなんだか知らないが、これはどうみても欠点だと思っている。Modelのコードを見ただけでどういう情報が入っているかわからない。migrationのコードはツギハギだらけで後から見るには向いていない。どういうModelか、ということを知るためには、動いているデータベースにアクセスしてスキーマ情報を見るしかない。かっこ悪い。


ってなことを、漠然と思っていた頃に、タイミングよくNoSQL(KVS)ブームが到来。「ああ、これだ」と思って、ブームに乗っかって、色々なKVSを試している中で、

「これなら最近のWeb開発の多くの部分でRDBMSを捨ててもいけるんじゃないかな」

と感じさせてくれたのがMongoDBだった。

数あるKVSの中でMongoDBの何がよかったのかと言うと、

  1. RoRのModelにぴったりと合いそう。上にも書いたように、KeyとValueの関係が、そのままModelのIdとInstanceの関係になりそう。
  2. Valueの部分はスキーマフリー&ダイナミックに作成可能なので、Ruby側のコード主導でカラムの追加をすることができる。Rubyのコードでのカラムの定義が「正」になる。もちろんDRYも守られたまま。
  3. SQL-likeなこともできる。where句(のようなもの)を指定したり、maxとかminとかgroup byも使えるし、やろうと思えばストアドプロシージャ(Javascript)のようなこともできる。この辺は、SQL脳の人(チーム)にとっては移行するためのハードルが低そう。
  4. 上記を踏まえた上で、KVSらしく、RDBMSでは厄介なスケールさせることも考えられていて、Shardみたいなこともデフォルトで用意されている。

とまあ、こんなところ。

つまり、最近のリッチなフレームワークの中では、DB側にそれほどリッチな機能はいらない。RDBMSはそのいらないリッチさがあり、そのせいでスケールさせるのが難しくなったりもしている。だったら、軽量でコンパクト、でもそれなりの機能を持って、そしてスケールしやすいMongoDBで十分なんじゃないのかな、と思った。

もしMongoDB始めてみようって人がいたら、こちらをどうぞ

追記: CouchDB編もできたみたいです。私は、Railsは好きです。念のため。


記事の内容についての質問、苦情、間違いの指摘等なんでもtwitterでどうぞ。