MongoDB
ドキュメント指向データベース
Tutorials
http://docs.mongodb.org/master/tutorial/
Java Driver for MongoDB
http://docs.mongodb.org/ecosystem/drivers/java/
MongoDB クライアント
特徴:スキーマレス(カラムが固定されない)、パフォーマンス高い、スケーラブル
利用場面:ビッグサイズ、重要度が低いデータの保存、リアルタイム性
不適場面:Transaction必要、複数テーブルからの複雑なクエリ
★Ubuntuにインストール
#公開鍵の設定
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
#/etc/apt/sources.list.d/mongodb.listの作成
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
sudo apt-get update
sudo apt-get install mongodb-10gen
★起動
サービス起動
mongod --dbpath D:\mongodb\db
★MySQL vs MongoDB
構造
SQL文
sudo service mongodb start
sudo service mongodb stop
sudo service mongodb restart
httpによりMongoDB状態を確認
http://localhost:27017/
http://localhost:28017/ webコンソール
シェルクライアント
mongoコマンド
mongo [DB名] [xxx.js] 外部ファイル
コマンド --help
★シェルクライアントのコマンド
help コマンド一覧
use test データを切り替え
db カレントDB
db.stats()
db.help() カレントDBのメソッド一覧
db.コレクション.help() コレクションのメソッド一覧
db.system.users.find() ユーザ一覧
show users
db.system.users.remove()
show dbs
db.dropDatabase()
show collections
db.createCollection("xxx")
db.コレクション.getIndexes() Index一覧
db.コレクション.drop()
db.コレクション.renameCollection("xxx")
load("xxx.js")
★Indexについて
> db.person.find({"name":"andy"}).explain()
Index使用しない
{
"cursor" : "BasicCursor", 全件検索
"isMultiKey" : false,
"n" : 1, 結果の行数
"nscannedObjects" : 5,
"nscanned" : 5, 全件スキャン
"nscannedObjectsAllPlans" : 5,
"nscannedAllPlans" : 5,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0, 実行時間
"indexBounds" : {
},
"server" : "xxx:27017"
}
Index使用する
{
"cursor" : "BtreeCursor name_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"name" : [
[
"andy",
"andy"
]
]
},
"server" : "xxx:27017"
}
★DBバックアップ、DB回復、Read-Write分離
●Master-Slave方式
mongod --dbpath D:\mongodb\dbM --master
mongod --dbpath D:\mongodb\dbS1 --port 8888 --slave --source 127.0.0.1:27017
mongo 127.0.0.1:27017
mongo 127.0.0.1:8888
●Replica Sets方式
mongod --dbpath D:\mongodb\dbR1 --port 2222 --replSet testR/127.0.0.1:3333
mongod --dbpath D:\mongodb\dbR2 --port 3333 --replSet testR/127.0.0.1:2222
mongod --dbpath D:\mongodb\dbR --port 4444 --replSet testR/127.0.0.1:2222
mongo 127.0.0.1:2222/admin
環境構築
>初期化
db.runCommand({"replSetInitiate":{
"_id":"testR",
"members":[
{
"_id":1,
"host":"127.0.0.1:2222"
},
{
"_id":2,
"host":"127.0.0.1:3333"
}
]
}
})
或いは
var config = {_id: 'testR', members: [
{_id: 1, host: '127.0.0.1:2222'},
{_id: 2, host: '127.0.0.1:3333'}]
}
rs.initiate(config)
>追加
rs.addArb("127.0.0.1:4444")
環境確認
rs.status()
↓結果
{
"set" : "testR",
"date" : ISODate("2013-07-20T15:19:10Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "127.0.0.1:2222",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 436,
"optime" : Timestamp(1374333508, 1),
"optimeDate" : ISODate("2013-07-20T15:18:28Z"),
"self" : true
},
{
"_id" : 2,
"name" : "127.0.0.1:3333",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 366,
"optime" : Timestamp(1374333508, 1),
"optimeDate" : ISODate("2013-07-20T15:18:28Z"),
"lastHeartbeat" : ISODate("2013-07-20T15:19:10Z"),
"lastHeartbeatRecv" : ISODate("2013-07-20T15:19:10Z"),
"pingMs" : 0,
"syncingTo" : "127.0.0.1:2222"
},
{
"_id" : 3,
"name" : "127.0.0.1:4444",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 42,
"lastHeartbeat" : ISODate("2013-07-20T15:19:10Z"),
"lastHeartbeatRecv" : ISODate("2013-07-20T15:19:08Z"),
"pingMs" : 0
}
],
"ok" : 1
}
>127.0.0.1:2222が停止
{
"set" : "testR",
"date" : ISODate("2013-07-20T15:20:51Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "127.0.0.1:2222",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : Timestamp(1374333508, 1),
"optimeDate" : ISODate("2013-07-20T15:18:28Z"),
"lastHeartbeat" : ISODate("2013-07-20T15:20:50Z"),
"lastHeartbeatRecv" : ISODate("2013-07-20T15:20:24Z"),
"pingMs" : 0
},
{
"_id" : 2,
"name" : "127.0.0.1:3333",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 528,
"optime" : Timestamp(1374333508, 1),
"optimeDate" : ISODate("2013-07-20T15:18:28Z"),
"self" : true
},
{
"_id" : 3,
"name" : "127.0.0.1:4444",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 141,
"lastHeartbeat" : ISODate("2013-07-20T15:20:50Z"),
"lastHeartbeatRecv" : ISODate("2013-07-20T15:20:49Z"),
"pingMs" : 0
}
],
"ok" : 1
}
★Shardingについて
mongod --dbpath D:\mongodb\db --port 2222
mongos --port 3333 --configdb 127.0.0.1:2222
mongod --dbpath D:\mongodb\dbSh1 --port 4444
mongod --dbpath D:\mongodb\dbSh2 --port 5555
mongo 127.0.0.1:3333/admin
db.runCommand({"addshard":"127.0.0.1:4444","allowLocal":true})
db.runCommand({"addshard":"127.0.0.1:5555","allowLocal":true})
db.runCommand({"enablesharding":"test"})
db.runCommand({"shardcollection":"test.person","key":{"name":1}})
大量データを入れた前
db.printShardingStatus()
↓結果
--- Sharding Status ---
sharding version: {
"_id" : 1,
"version" : 3,
"minCompatibleVersion" : 3,
"currentVersion" : 4,
"clusterId" : ObjectId("51ebb8a481549425b79cac30")
}
shards:
{ "_id" : "shard0000", "host" : "127.0.0.1:4444" }
{ "_id" : "shard0001", "host" : "127.0.0.1:5555" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "test", "partitioned" : true, "primary" : "shard0000" }
test.person
shard key: { "name" : 1 }
chunks:
shard0000 1
{ "name" : { "$minKey" : 1 } } -->> { "name" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 0)
大量データを入れた後
for(var i=0; i<100000; i++){
db.person.insert({"name":"andy "+i,"age":i})
}
db.printShardingStatus()
↓結果
--- Sharding Status ---
sharding version: {
"_id" : 1,
"version" : 3,
"minCompatibleVersion" : 3,
"currentVersion" : 4,
"clusterId" : ObjectId("51ebb8a481549425b79cac30")
}
shards:
{ "_id" : "shard0000", "host" : "127.0.0.1:4444" }
{ "_id" : "shard0001", "host" : "127.0.0.1:5555" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "test", "partitioned" : true, "primary" : "shard0000" }
test.person
shard key: { "name" : 1 }
chunks:
shard0000 2
shard0001 1
{ "name" : { "$minKey" : 1 } } -->> { "name" : "andy 0"} on : shard0000 Timestamp(2, 1)
{ "name" : "andy 0" } -->> { "name" : "andy 9999" } on : shard0000 Timestamp(1, 3)
{ "name" : "andy 9999" } -->> { "name" : { "$maxKey" : 1 } } on : shard0001 Timestamp(2, 0)
★groupについて
サンプル1
db.person.group({
"key":{"age":true},
"initial":{"person":[]},
"reduce":function(cur,prev){
prev.person.push(cur.name);
}
})
↓結果
[
{
"age" : 27,
"person" : [
"andy",
"jane"
]
},
{
"age" : 28,
"person" : [
"tom"
]
},
{
"age" : 31,
"person" : [
null,
"mike"
]
}
]
サンプル2
db.person.group({
"key":{"age":true},
"initial":{"person":[]},
"reduce":function(cur,prev){
prev.person.push(cur.name);
},
"finalize":function(out){
out.count=out.person.length;
},
"condition":{"age":{$lt:30}}
})
↓結果
[
{
"age" : 27,
"person" : [
"andy",
"jane"
],
"count" : 2
},
{
"age" : 28,
"person" : [
"tom"
],
"count" : 1
}
]
★mapReduceについて
var map = function(){emit(this.age, {count:1})}
var reduce = function(key, value){
var result = {count:0};
for(var i = 0; i < value.length; i++){
result.count += value[i].count;
}
return result;
}
※keyはemitのkeyと同じ、valueはemitのvalueと同じ
db.person.mapReduce(map,reduce,{"out":"collection"})
↓結果
{
"result" : "collection",
"timeMillis" : 461,
"counts" : {
"input" : 5,
"emit" : 5,
"reduce" : 2,
"output" : 3
},
"ok" : 1,
}
db.collection.find()
↓結果
{ "_id" : 27, "value" : { "count" : 2 } }
{ "_id" : 28, "value" : { "count" : 1 } }
{ "_id" : 31, "value" : { "count" : 2 } }
★運用について
●サービス登録
コマンドプロンプトを管理者モードで起動
mongod --dbpath D:\mongodb\db --logpath D:\mongodb\log.txt --port 2222 --install
mongod --dbpath D:\mongodb\db --logpath D:\mongodb\log.txt --port 2222 --auth --reinstall
net start MongoDB
●監視
1.httpによる監視
2.db.serverStatus()
3.mongostatコマンド(リアルタイム監視)
mongostat --port 2222
●認証・認可
mongo 127.0.0.1:2222/admin
> db.addUser("admin","admin")
{
"user" : "admin",
"readOnly" : false,
"pwd" : "7c67ef13bbd4cae106d959320af3f704",
"_id" : ObjectId("51ebc5e9539fe170fffc53f5")
}
> db.addUser("andy","andy",true)
{
"user" : "andy",
"readOnly" : true,
"pwd" : "d09b3fdc22d3f9fea603f98b9ce67120",
"_id" : ObjectId("51ebc638539fe170fffc53f6")
}
> db.auth("admin","admin")
> db.auth("andy","andy")
●バックアップ・回復
1.mongodumpコマンドとmongorestoreコマンド
サービス停止は必要なし
※リアル性が欠ける(メモリに残るデータ)
mongodump --db test
mongorestore --drop
mongodump --port 2222 -d test -o D:\mongodb\backup
mongorestore --port 2222 -d test --drop D:\mongodb\backup\test
2.Master-Slaveにより
3.fsync+lock
リアル性保証(メモリに残るデータをディスクに書き込む)
ロック制御:db.runCommand({"fsync":1,"lock":1})
ロック解除:db.$cmd.unlock.findOne()
★Performance改善
1.遅い処理を調べる: db.setProfilingLevel(1, 100);
2.explain分析、mtoolsでログを分析
3.index作成、Indexes in the Background、Sparse Indexes
4.write(master)とread(slave)を分離