capped collectionのmapReduceでの挙動
capped collectionはサイズが固定されて、溢れると捨てる、という挙動とトレードオフに高速な書き込み性能を実現しています。
Capped Collections - MongoDB
ということは、 id:doryokujin さんの Sharding を使いこなすための5つのTips - doryokujin's blogで見られたように、SSDをmapReduceの出力先であるprimaryとしなくてもcapped collectionを指定すればいいのではないか、と思い、実験してみました。
capped collectionの作成
> db.createCollection('cappedmr', {capped:true, size: 1000000000}) > db.createCollection('uncappedmr') > db.cappedmr.isCapped() true > db.cappedmr.isCapped() false > mapReduce(m, r, option)
として、mapReduceの処理を行います。
ところが、
> db.target.mapReduce(m, r, {out: "cappedmr"}); { "result" : "cappedmr", "timeMillis" : 21764, "counts" : { "input" : 450954, "emit" : 450954, "output" : 78855 }, "ok" : 1, } > db.target.mapReduce(m, r, {out: "uncappedmr"}); { "result" : "uncappedmr", "timeMillis" : 21896, "counts" : { "input" : 450954, "emit" : 450954, "output" : 78855 }, "ok" : 1, }
となんら変わらないパフォーマンスが出てしまいました。
mapReduceのoutにcappedを指定したほうが遅いのはなんでだろう #mongodb
twitterでこぼしたところ、
@muddydixon 1つはcappedの作成コストは指定容量を確保するなど、それなりに高いはずなのでreplaceオプションで再作成する際の時間が処理時間を上回ったのでは。cappedを指定しているのにmergeやreduceオプションが使えると、cappedではない
2011-06-16 14:21:17 via YoruFukurou to @muddydixon
@muddydixon コレクションが作成されている可能性もありますねぇ。
2011-06-16 14:21:32 via YoruFukurou to @muddydixon
と助けの声が出ました。
打ち合わせに出てて放置していたら、さらに、
@muddydixon MapReduceのoutputがデフォのreplaceだと、一旦コレクションをdrop()するのではじめに作成していても意味ないかもしれません。 URL 418行目。再作成ではcappedでないのが作られてないですかねぇ
2011-06-16 15:21:02 via YoruFukurou to @muddydixon
@muddydixon MRの出力コレクションに対して、 db.collname.isCapped() って打ってもらうと、cappedかどうか確認できまする
2011-06-16 15:22:46 via YoruFukurou to @muddydixon
@muddydixon 既存の同名コレクションは削除され、tmpコレクションが内部的に作成され処理完了後にリネームする形で指定コレクションに出力される形ではないですかね?なのでCappedは使えないのではと思います。他のreplaceやmergeはupdate操作が必要ですし
2011-06-16 15:55:52 via YoruFukurou to @muddydixon
とのこと。
せっかくcappedを作っても、mapReduceでは「tmp.mr.target_capped_24_inc」こんな感じの仮collectionを作り、その後でoutで指定した目的のcollectionにrenameするようです。
> db.cappedmr.isCapped()
false
えぇー
一応、すべてのmapReduceのoutput optionで検証しました。
> db.target.mapReduce(m, r, {out: "cappedmr"}); > db.cappedmr.isCapped() false > db.target.mapReduce(m, r, {out: {replace: "cappedmr"}}); > db.cappedmr.isCapped() false > db.target.mapReduce(m, r, {out: {merge: "cappedmr"}}); > db.cappedmr.isCapped() false > db.target.mapReduce(m, r, {out: {reduce: "cappedmr"}}); > db.cappedmr.isCapped() false > db.target.mapReduce(m, r, {out: {reduce: db.cappedmr}}); > db.cappedmr.isCapped() false > db.target.mapReduce(m, r, {out: {reduce: db.createCollection("cappedmr", {capped: true, size: 1000000000})}}); Thu Jun 16 16:18:12 uncaught exception: map reduce failed:{ "assertion" : "unknown out specifier [errmsg]", "assertionCode" : 13522, "errmsg" : "db assertion failure", "ok" : 0 }
全部ダメポ・・・
というわけで
SSDを使いましょう。