Skip to content
irasally edited this page Dec 20, 2012 · 50 revisions

丸の内MongoDB勉強会で出た質問を中心にMongoDBに関するノウハウやTipsをまとめます。

Table of Contents

全般

rpmはどこで配布されていますか

githubで公開されています。
https://github.com/mongodb/mongo/tree/master/rpm

起動スクリプトはありますか=

作りました。
https://github.com/syokenz/mongodb-init-script
もしくは、mongodユーザ/mongodグループを作成してrpmのものを使ってください。
https://github.com/mongodb/mongo/blob/master/rpm/init.d-mongod

mongod.confのサンプルはありますか

githubからrpm用のものを取得してください。
https://github.com/mongodb/mongo/blob/master/rpm/mongod.conf

dbpathを指定しない場合、データはどこに作成されますか

mongodの起動オプションで--dbpathを指定しなかった場合、/data/db または C:\data\db に作成しようとして、ディレクトリが無かった場合はエラーで起動しません。
このファイルで定義してるっぽい。
https://github.com/mongodb/mongo/blob/master/src/mongo/db/pdfile.cpp
line:147

#ifdef _WIN32/
    string dbpath = "\\data\\db\\";
#else
    string dbpath = "/data/db/";

db.collection.remove()とdb.collection.drop()の違いは何ですか

remove()はコレクションが残ります。drop()はコレクションごと削除します。
show collections で確認できます。

> db.marunouchi.remove() //コレクションの中のすべてのオブジェクトを削除します  
> show collections //確認、marunouchiはまだある
> db.marunouchi.drop() //コレクションを削除します
> show collections //確認、marunouchiはない

journal機能ってなんですか

・ver.2.0 から標準機能で、データ書き込み前にオペレーションを journal ログに保存(先行書き込みログWAL)することでデータの安全性を向上させます。
・100ms毎(デフォルト)に journal ログに書き込みが行われます。(journalCommitIntervalで変更可能)
・予期せぬサーバーダウンからの復帰もjournaling機能によってデータがリカバリーされます。

[ダウンからのデータリカバリプロセス]
[1] クリーンシャットダウン時に journal サブディレクトリは削除
[2] サーバーダウン時には journal サブディレクトリはそのまま残る
[3] mongod は起動時に journal サブディレクトリが無いかチェック
[4] あればそのディレクトリ内の journal ファイルからダウン時に未
実行だったオペレーションを実行する
出所:はじめてのMongoDB

Mongo Shell

コマンド一覧が見たい

helpコマンドで見れます。

help
db.help()
db.mycoll.help()
rs.help()
sh.help()
または、ドキュメントを見てください。
JavaScript Interface

コマンドを覚えきれません

mongo shellではTAB補完ができます。

コマンドをSQLと比較して見たい=

第1回勉強会の資料を参照してください。
SQLライクなMongoDBの操作

mongo shellのJavaScript実行環境は何ですか

ドキュメントにはextended SpiderMonkey shellとあります。
mongo - The Interactive Shell

mongo shellにv8は使えますか

ビルド時のオプションで選択できるようになっているようです。
https://github.com/mongodb/mongo/blob/master/SConstruct

# library choices
add_option( "usesm" , "use spider monkey for javascript" , 0 , True )
add_option( "usev8" , "use v8 for javascript" , 0 , True )
...
if ( not ( usesm or usev8 or justClientLib) ):
    usesm = True
    options_topass["usesm"] = True
また、2.3.xからv8がデフォルトになるとのことです。
Switch to v8

テストデータを簡単にインサートしたい

mongo shellはJavaScriptを評価しますので、こんな感じで

> for(var i=1; i<=1000; i++) db.logs.insert({"uid":i, "value":Math.floor(Math.random()*1000+1)})

こんなのも

> people = ["Marc", "Bill", "George", "Eliot", "Matt", "Trey", "Tracy", "Greg", "Steve", "Kristina", "Katie", "Jeff"];
> for(var i=0; i<1000000; i++){
                             name = people[Math.floor(Math.random()*people.length)];
                             user_id = i;
                             boolean = [true, false][Math.floor(Math.random()*2)];
                             added_at = new Date();
                             number = Math.floor(Math.random()*10001);
                             db.test_collection.save({"name":name, "user_id":user_id, "boolean": boolean, "added_at":added_at, "number":number });
}
出所:レプリカセットを複製した分割クラスタに変換する

find()で20件以上表示させたい

> DBQuery.shellBatchSize = 300 //最大表示数の変更
> db.marunouchi.find()
もしくは
> db.marunouchi.find().toArray()  
> db.marunouchi.find().toArray().forEach(printjsononeline)  

insert()とsave()の違い

save()は条件によって更新処理を行います。insert()は更新処理は行いません。

update()とsave()の違い

引用元:mongodbのupdateとsaveの違い

update() 第一引数に当てはまる条件に一致した「最初の」データを第二引数のデータに書き換える。 第三引数(upsert)を有効にしていれば、条件に一致するデータがない場合はデータが登録される。 第四引数(multi)を有効にしていれば、条件に一致したすべてのデータを書き換える。
save() _id(mongodbが自動的に振るドキュメントid)が第一引数に含まれれば、upsert = trueの updateを行い、なければ insert を行う。
参考:Updating

外部jsファイルを読み込む

$ mongo
> load('/home/admin/js/insert.js');
もしくは
$ mongo {hostname}/{dbname} insert.js
//例
$ mongo localhost:27017/test insert.js

Operator($から始まるやつ)を全部知りたい

マニュアルにリストがあります。
http://docs.mongodb.org/manual/reference/operators/

Sharding

chunk migration中にcountの結果が正しく返らない問題の回避策はありますか

Sharding環境で大量データinsert後にchunkの移動(migration)が起こり、その際にcount()すると実際のデータよりも多くカウントされてしまいます。
以下の回避策が考えられます。

  • Auto Balancerをオフにして手動でmigrationする、またはスケジューリングしてmigrationのタイミングを調整する Schedule the Balancing Window
  • mongosからsh.isBalancerRunning()でmigration中かどうかわかるのでアプリ側で回避する

Shardingでは、localhostと実IPの混在はできません

mongosサーバを起動する際のconfig serverの指定と、shard追加時のaddshardの指定を注意してください。このエラーが出たら、localhostと実IPが混在していないかを確認してください。

"can't use localhost as a shard since all shards need to communicate. 
either use all shards and configdbs in localhost or all in actual IPs host: localhost:xxxxx isLocalHost:0"

一度Sharding環境に所属したノードが、同じdbで他のSharding環境に所属はできません

dbを削除してください。

Shard Keyにはどのようなフィールドを指定すればよいでしょうか

Mongo shardingより引用
悪い例

  • 密度の低いkey
    • 例:大陸名
    • 主にカテゴリデータなどの離散データ、N個のカテゴリーならN個にしか分散できない
  • Shard keyの値が増えて行くのみのデータ
    • 例:Time、autoincrementするObjectID(自動で入れてくれるやつ)
    • ($CurrentMax, +∞]のChunkだけがひたすら分割、明らかにShard間で不均一がおこる
  • Random Shard Key
    • 均等分散するけど非常に大きな範囲を持ったchunkが存在する可
    • 例:MD5 hash
良い例
  • 緩く増加していくキー + 検索でよく使われるキー
    • 例:アクセス解析{month:1, user:1}
    • ("2011-04","user-1"),("2011-04","user-2")...
    • 左のキーは一定期間固定で、右のキーはほぼ均等に分布してくれる
良いShard Keyのイメージ
長い時間が経ってShardの偏りが起き始めるころに、片方のキーが増加してShardをリフレッシュしてくれる。

参考:「ニフティクラウドでMongoDBは使えるか?」を読んで、僕なりの考察を書いてみた

MongoDB のshardingでは、1番始めに行う「Shard Keyの設定」が非常に重要です。このshardKeyの設定次第では、shard間の偏りや
データの非効率な取得が生じてしまう原因になります。また、find()やinsert()などの処理に関してもそのshardKeyを条件に含めて
実行するかどうかで効率性が大きく異なってきます。

連続して同じサーバに書き込みにいかないように設計するのが大切。
第25回 MongoDB最前線! 効果的なシャーディングとバックアップ

検証環境用に構築スクリプトはありますか

mongoリポジトリにExample of using MongoDB auto-shardingがあります。
私が作成したものもありますのでよかったら使ってください。
シャーディング環境構築スクリプト

Replica Set

Primary障害時のSecondaryからPrimaryへの昇格で、優先度は設定できますか

priority設定できます。選出基準は、1.priorityが最大、2.primaryとの最終同期が最新、3.votes値が高いで決まるようです。
参考:うまく動かすMongoDB仕組みや挙動を理解するの中程

Replica Setの最小構成はいくつですか

Primary 1つ、Secondary 1つの2台から構成可能です。
ただし、推奨はPrimary 1つ、Secondary 2つの3メンバーセットです。
レプリケーションアーキテクチャ

運用

RepairDatabase

突然の電源が落ちて、OS起動後に以下のようなエラーメッセージでMongoDBが起動できなくなった場合は、repairコマンド。

**************
Unclean shutdown detected.
Please visit http://dochub.mongodb.org/core/repair for recovery instructions.
*************
repairコマンド
$ mongod --dbpath=(dbpath) --repair