MongoDBの11のがっかりバギー

残念なところは、僕も直面していたのもあり、していないのもあるので、leifw: 11 Buggy Disappointments in MongoDBを掻い摘んでみました。
やっつけの訳で申し訳ない・・・

3、4、6が怖すぎる・・・

1.

undefined 要素をもつ配列を含む document を dump (例えば、 BSON format でエクスポート)して、そのデータをインポートすると、undefinedな要素が消えます。値のインデックスが変わります。例えば、こんな漢字のメンバを含む document をエクスポートします。

var a = [];
a[0] = "a";
a[2] = "c";

インポートすると "c" の位置が、2から1に移った ["a", "c"] という配列が得られます。

2.

shared collection からデータをエクスポートすると、 shard の1つからのみのデータがアウトプットされてしまう。

3.

shard collection に大規模なデータ(~10GB)をインポートしたあと、 mapReduce は合理的な説明なく失敗するという、奇妙で一貫性の無い問題に出会した。

4.

Mongo の db.eval() はドキュメントにあるよりもはるかに危険です。もし、節度を守ったバカでメモリを沢山使うことをした場合、 segfault を引き起こし、リカバリが必要な状態のデータストアを残すほどに server を OOM に導きます。

5.

mapReduce に 渡された JavaScript の map / reduce 関数は、通常 JavaScript に期待されるスコープの中の変数や関数を把握することができません。mongo の解決方法は、 mapReduce に scope 引数として渡すことでした。
残念なことに、 scope は関数を渡せません。(※訳者注:collectionも渡せません) 私が言える範囲でいうと、 Mongo のアプローチは、db.system.js collection に関数を追加することです。これはコードメンテナンス性が低いとても悲しい解決方法です。

6.

説明できないのですが、数時間動作した後に、map と reduce 段階の両方を完全に通過して、そののちにdb.system.jsで定義された関数が未定義であるとレポートして mapReduce ジョブが落ちていました。
もし、未定義なら、5千万回も呼び出す前に未定義を報告するべきだと思います。同じ mapReduce ジョブは shard していない collection で行った小さなサンプルデータでは成功しています。

7.

Mongo の mapReduce はシングルスレッドです。身震いしました?本当です。どんなに多くの mapReduce ジョブをあなたが投げようとも一度にひとつです。CPU 利用は100%に上ります。 Mongo で mapReduce の為にひとつ以上のコアを利用したい時には、同じマシンで複数の shard を必要とします。しかし、現実的には非効率なアプローチです。 たとえ、馬鹿げている程サイズの小さなチャンクにセットした時でさえ、私が shard を望むときには Mongo は shard されていません。

8.

マルチコアで mapReduce を走らせたくて、 shard するならば、 primary が多くのメモリを食い、 secondary shard サーバたちが枯渇するのを目のあたりにするでしょう。

9.

100GB partition の Mongo を VM で動かしました。異なるテーブルに出力し、多くのディスクスペースを使用する、いくつかの異なる mapReduce ジョブを走らせました。そのうちのひとつのジョブがハングしました。利用可能な領域が2GB以下しか残されておらず、 Mongo は他の slab に割り当てられていませんでした。残念なことにクライアントにはこれを説明するメッセージは返されていません。

10.

空き領域を確保するために、collection のすべての document を削除して、これらをdrop しようとしました。どんな理由であれ、これらのことをしたとしても Mongo はいかなる空き領域を実際にはつくりませんでした。利用できない解放された領域を再定義してみるために、クラスタを切り離してみました。しかしながら、イライラすることに、 Mongo doc がいうには、"この [削除された] 領域は、OSに開放されず再利用されます" とあるのです。

11.

mongo doc は、その空き領域をOSに返して欲しければ、 DB をリペアするべきだとあるので下記コマンドを試してみました。

db.repaireDatabase()

残念なことに、ディスクがいっぱいの場合、 Mongo はリペアする空間すら確保できないでしょう。試したところ、下記のようなエラーがでました。

Cannot repair database X having size: 21415067648 (bytes) because free disk space is: 887955456 (bytes)

まとめ

Mongo の素敵なところはたくさんありますが、これらの点で、私は、Mongo の mapReduce 機能はシリアスなデータを噛み砕くのではなく、メモリに合わせるには大きすぎるクエリを走らせることに向いていると感じています。おそらく、 私が直面した難しさは、 mapReduce が関与する sharding を行った為だと思います。また、shard の設定において致命的な過ちをしている可能性もあります。しかし、かなり念入りに指示に従ったと思っているのですが。。。