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,
}

となんら変わらないパフォーマンスが出てしまいました。


twitterでこぼしたところ、


と助けの声が出ました。

打ち合わせに出てて放置していたら、さらに、




とのこと。

せっかく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を使いましょう。