SlideShare a Scribd company logo
後悔しない
もんごもんごの使い方
∼アプリ編∼
松下 雅和(@matsukaz)
自己紹介
•松下 雅和
•サーバ寄りのエンジニア
•Twitter: @matsukaz
•あだな:まつかず
•DevLOVE スタッフ
今日の話
•開発しやすいってほんと?
•おすすめライブラリ
(Java/Node.jsの話)
•データ設計はどうやるの?
•こういう使い方するといいかも
開発しやすいって
ほんと?
ほんとだよ!
公式ドキュメントにも
MongoDB is an open-source, document-
oriented database designed for ease of
development and scaling.
MongoDBは、開発しやすさとスケールしやすさを目
指したオープンソースのドキュメント指向DBです。
と書いてある
開発しやすい
ポイント①
インストールが簡単!
環境ごとのファイルを
DLして展開するだけ
もろもろの
パッケージにも対応
あとは起動するだけ
$ bin/mongod --fork 
--dbpath ./data 
--logpath ./logs/mongod.log
※ 必要最小限なオプションのみ
なにこれ
簡単すぎ…?
@mongodb
>>あなたの適正もんごは?
開発しやすい
ポイント②
スキーマレス
どころか、
DBやコレクションの
作成も不要
(勝手に作られる)
$ bin/mongo
> use db1; // 操作するとDBが作られる
switched to db db1
// collectionが存在しなかったら作られる
> db.user.save( { name : "matsukaz" } );
つまり
簡単に使う分には
DB側の準備が
全くいらない
まぢかよもんご!!!!
クールすぎるぜもんご!
そこにしびr(ry
開発しやすい
ポイント③
ドキュメント指向
RDBでやってた
正規化とか
めんどくない?
階層構造で持てるなら
非正規化のままでも
いいんでない?
プログラム上の
オブジェクト構造を
そのまま永続化も
可能だし
試しに
Node.jsで実装してみる
$ npm install mongodb # ドライバーのインストール
$ vi index.js
$ node index.js # 実行
{ name: 'matsukaz', _id: 51f7efbed66a41de0f000001 }
var MongoClient = require("mongodb").MongoClient;
var url = "mongodb://127.0.0.1:27017/db1";
var data = {name : "matsukaz", age : 34}; // 作成したデータ
MongoClient.connect(url, function(err, db) { // 接続
var userColl = db.collection("user");
userColl.save(data, function(err) { // データを保存
userColl.findOne({name: "matsukaz"}, function(err, user) { // 名前で検索
console.log(user);
process.exit(0);
});
});
});
後悔しないもんごもんごの使い方 〜アプリ編〜
こんだけ簡単だと
使わない手はないよね!
おすすめライブラリ
Java
•mongo-java-driver
• https://github.com/mongodb/mongo-java-driver
•MongoDBの公式ドライバー
•ローレベルAPIなので操作はかなり面倒
Java
•mongo-java-driver
•コネクションプールのチューニングは必須
項目 意味 値
connectionsPerHost コネクション数 100
threadsAllowedToBlockForC
onnectionMultiplier
1コネクション辺りの接続
待ち数
4
•上記の例だと、プールの上限は
100 + (100 * 4) = 500
Java
•Spring Data - MongoDB
• http://www.springsource.org/spring-data/mongodb
•ドキュメントとPOJO間マッパー
•mongo-java-driverを内部で利用
public class User {
private String id;
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// 各プロパティのgetter
}
MongoTemplate mongoTemplate =
new MongoTemplate(new Mongo(url), "dbname");
// ドキュメント作成
mongoTemplate.insert(new User("matsukaz", 34));
// ドキュメント取得
User matsukaz = mongoTemplate.findOne(
new Query(Criteria.where("name").is("matsukaz")},
USer.class);
Javaでも
言うほど相性は
悪くない
Node.js
•node-mongodb-native
• https://github.com/mongodb/node-mongodb-native
•MongoDBの公式ドライバー
•スキーマ定義が不要ならこれで
require("mongodb").MongoClient.connect(url, function(err, db) {
var userCollection = db.collection("user");
// ドキュメント作成
userCollection.save({name:"matsukaz", age:34}, function(err){
// ドキュメント取得
userCollection.findOne({name: "matsukaz"}, function(err, docs){
console.log(docs);
});
});
});
Node.js
•Mongoose
• http://mongoosejs.com
•ドキュメントとオブジェクト間マッパー
•node-mongodb-nativeを内部で利用
var db = require("mongoose").connect(url);
// スキーマ定義が必要
var User = db.model("user", new Schema({
name : { type : String, unique : true},
age : Number
}));
var matsukaz = new User({name:"matsukaz", age:34});
matsukaz.save(function(err) { // ドキュメント作成&取得
User.findOne({name:"matsukaz"}, function(err, user){
console.log(user);
});
});
Node.jsと
本当に相性がいい!
MongoDBを使うと
「開発がしやすくなる」
のは伝わりました?
んでは次、
データ設計は
どうやるの?
開発は簡単だけど、
何も考えずに
データ構造を決めると
運用で死にます・・・
データ構造を決める上で
大事なポイントを整理
BSONの特徴に合わせる
•BSONは複雑なデータ構造を扱える
•RDBとは違い、積極的に階層化/非正規化
{
"facebookId" : xxx,
"status" : { "lv" : 10, "coin" : 9999, ... },
"layerInfo" : "1¦1¦0¦1¦2¦1¦1¦3¦1¦1¦4¦0...",
"structure" : {
"1¦1" : { "id" : xxxx, "depth" : 3, "width" : 3, ... },
"4¦8" : { "id" : xxxx, "depth" : 2, "width" : 2, ... }
},
"neighbor" : [ { "id" : xxx, ... }, { "id" : xxx, ... } ]
}
BSONの特徴に合わせる
•スキーマレス = データ構造の変更が容易
•開発を進めながら最適な構造にしていく
•後方互換性も意識する
{
"dataId" : xxx,
"update" : {
"user" : xxx,
"time" : xxx,
"from" : "API"
}
}
{ "dataId" : xxx,
"updateUser" : xxx }
{ "dataId" : xxx,
"update" : {
"user" : xxx
}
}
互換性を保ち
やすい構造で
項目の追加は
互換性が保ちやすい
BSONの特徴に合わせる
•リレーションは、パフォーマンスも考えた上
で、利用の有無とやり方を検討
•独自IDを利用
•ObjectIdを利用
•DBRefを利用
{ "userId" : 123,
"manager" : 456 }
{ "userId" : 123,
"manager" : ObjectId("4ba550e2b...") }
{ "userId" : 123,
"manager" : DBRef("user", ObjectId("4ba550e2b...")) }
データ型の差異に注意
•クライアントによっては、データ型のマッピン
グが異なるので注意が必要
•コンソール(mongo)
•import/exportツール
•言語別のドライバー/ライブラリ
苦手な部分は事前に考慮
•トランザクションはない前提で
•1ドキュメントにおけるデータ量/フィールド
数が多すぎないように
•場合によってはデータを圧縮
"layerInfo" : {
"1¦1" : 0,
"1¦2" : 1, ...
}
"layerInfo" : "1¦1¦0¦1¦2¦1¦1¦3¦1¦1¦4¦0..."
苦手な部分は事前に考慮
•DBレベルのロックがかかる(v2.4時点)の
で、アクセス頻度は極力減らす
•場合によっては、同じシステム内のコレク
ションでも、複数のDBに分割して保存する
シャードキーは慎重に
•カーディナリティが低い値は使わない
•利用頻度の高いデータがメモリ上に乗り、低い
データはメモリ上に乗らないように
•参照や更新が多いデータはバランスよく各
Shardに分散
シャードキーは慎重に
•極力Targetedオペレーションにする
•Shard Keyでデータを操作
•Shard Key以外の操作はIndexを利用
Operation Type
db.foo.find( { ShardKey : 1 } ) Targeted
db.foo.find( { ShardKey : 1, NonShardKey : 1 } ) Targeted
db.foo.find( { NonShardKey : 1 } ) Global
db.foo.insert( <object> ) Targeted
db.foo.update( { ShardKey : 1 }, <object> )
db.foo.remove( { ShardKey : 1 } )
Targeted
db.foo.update( { NonShardKey : 1 }, <object> )
db.foo.remove( { NonShardKey : 1 } )
Global
気をつける点は
それなりに多いけど、
もんごの特性を
理解していれば、
当たり前に考慮できる
ようになる・・はず
まずは
使ってみることが
大事!!
最後に、
こういう使い方すると
いいかもという話
プロトタイプ開発
•複雑なデータ構造を簡単に扱えるので、開発ス
ピード重視で作れる
•スキーマレスなので、実装しながらデータ構造
を変更できる
•ちょっとしたゲームのプロトタイプ開発
(+3回の仕様変更)が2週間で出来たよ
開発中
•開発中は以下のような方法を取ることが多い
•各自ローカルでMongoDBを起動して開発
•共用のMongoDBサーバを用意して用途別に
DBを割り当てる
•各自の開発用
•DEV環境用
•Jenkinsによる単体テスト用
負荷テスト
•コマンドラインツール(mongo)などから簡
単に大量データを投入
•chunk移動しまくるので落ち着くまで注意
> // 1000万件のテストデータを作成
> function pad(str, length) {
str = String(str);
while (str.length < length) str = "0" + str;
return str;
}
> for (var i = 1; i <= 10000000; i++) {
db.user.save({name: ("hoge" + pad(i, 10)) });
}
障害テスト
•障害を想定した動作検証は必ずやる。絶対。
•mongodが落ちた場合
•PRIMARYへ昇格するか
•復帰後にデータが正しく同期されるか
•mongocが落ちた場合に影響がないか
•mongosが落ちた場合のシステムの挙動
•バックアップから戻せるか
まとめ
•開発での利用はほんとに簡単!
•とりあえず作ってみよう!という場面
で使えるのはもちろん
•使いどころを間違えなければサービス
でもちゃんと使える
•もんごもんご!
宣伝!
•WEB+DB PRESS Vol.75 に
「MongoDB実践入門」を書
きました!
ご清聴
ありがとう
ございました!

More Related Content

後悔しないもんごもんごの使い方 〜アプリ編〜

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy