phpとmongodbで学ぶ次世代データストア
DESCRIPTION
ドキュメント指向データベースのMongoDBをPHPで扱う方法を説明しながら、RDBやKVSとの違いやメリットを紹介します。 at LOCAL DEVELOPER DAY '10 /Winter http://labs.nazone.info/TRANSCRIPT
提 供
LOCAL PHP部
PHP と MongoDB で学ぶ次世代データストア
佐藤琢哉LOCAL PHP 部
自己紹介• 佐藤琢哉 aka nazo• 旭川出身 東京在住• 株式会社 RYUS 所属 (http://ryus.co.jp)– 3月末まで
• LOCAL PHP 部• Hatena : nazone• twitter : nazo
突然ですが
4月から札幌市民に
なります!!!!!
友達が少ないので皆さん
遊んでやってください
アジェンダ• MongoDB って何?• 使い方• 他の DBMS との比較• MapReduce• まとめ
そもそも何の話?
MongoDB すごいよ!
MongoDB って何?
http://www.mongodb.org/
MongoDB (from "humongous") is a scalable, high-performance, open source, schema-free,
document-oriented database.
ドキュメント指向データベース• スキーマがない• データ定義自体が各ドキュメントに入っ
ている
RDBMSID 名前 年齢 性別 住所
行と列にデータを
当てはめていくのがRDBMS
ドキュメントの集合
ドキュメント指向
ID : 1名前: hokkai
性別:男
ID : 2名前: onodes
電話番号: xxx-xxx-xxxx
ID : 3名前: reath
ID : 4名前: riaf
ライブラリ: rhaco
※名前は実在の人物とは一切関係ありません
AGPL ライセンス• Web からのみアクセスするものでもソー
スコードを公開しないといけない GPL• 普通の GPL は、 Web サイトとして使う
分にはプログラムを配布するわけじゃないからソースコード公開する必要がないが、それが気にくわないために作られたライセンス
AGPL ライセンス• MongoDB 自体をカスタマイズするなら
例え Web サイト内部だけで使ってても公開要求に応じないと駄目よー
• 各言語からアクセスするドライバはApache License だから大丈夫よー
• 社内からしかアクセスできないような場所で使う分には平気よー
特長
データを BSON で保存• BSON is a binary-encoded serialization
of JSON-like documents• { hoge: "fuga", foo: [bar, baz] }• 構造が自由• XML データベースが JSON になったような
感じ• JSON なので操作も簡単• ちょっとした構造で JOIN とかする必要がな
い
JavaScript 処理系内蔵• MongoDB 単体で JavaScript でデータを
操作することが可能• JSON で記録されたデータをそのまま処理
できる• ストアドプロシージャ的な使い方• MapReduce
スケーラブル• MapReduce 搭載• Master-Slave 構成• ペア DB• Master-Master 構成(制限あり)• Sharding
なんで MongoDB なの?
日本だと CouchDB のほうが情報が圧倒的に
多いのになんでMongoDB とかマイ
ナーそうなのを…
提 供
LOCAL PHP 部
http://php.net/mongo
そりゃ MongoDB しかない!
ちなみに世界的には
青: CouchDB赤: MongoDB
使い方[ インストール ]
インストール• いろんなプラットフォームのバイナリが
配布されているので好きなのを入れる。
インストール• データフォルダをデフォルトで /data/db
に作るので、面倒であればフォルダを作っておく
• 起動時の設定でもちろん変更可能
インストール• mongod を実行するだけで起動• 面倒な人は init スクリプト– init.d for MongoDB– http://gist.github.com/232227
インストール• pecl install mongo• あと php.ini に extension=mongo.so
と書くだけ– PHPer 歓喜
使い方[PHP コード ]
接続• $mongo = new Mongo();• $mongo = new
Mongo("example.com:65432");
データベースとコレクションの取得
• $db = $mongo->selectDB( "dbname" );
• $col = $db->selectCollection( "collectionname" );
データベースとコレクション
RDBMS MongoDB
データベース データベース
テーブル コレクション
行(レコード) ドキュメント
INSERT
$doc = array( "name" => "MongoDB", "type" => "database", "count" => 1, "info" => (object)array( "x" => 203, "y" => 102), "versions" => array("0.9.7", "0.9.8",
"0.9.9"));$col->insert( $doc );
INSERT
• PHP の配列がそのままデータとして入る• 複雑な階層でももちろんそのまま入る• 1コレクション内の構造が統一されてい
なくてもいい(ただしインデックスを張る場合はその項目は必須)
INSERT
$doc = array( "name" => "Apple", "color" => "Red",);$col->insert( $doc );$doc = array( "name" => "Beer", "price" => 300,);$col->insert( $doc );
SELECT
• 1件取得$obj = $col->findOne();• 条件指定取得$obj = $col-
>findOne(array("name"=>"MongoDB"));
• 全件取得$cursor = $col->find();
SELECT
• $cursor = $col->find(array('num' => array('$gt' => 1)));
• $cursor = $col->find(array('name' => new MongoRegex('/ba/i')));
• $cursor = $col->find(array('$where' => 'this.num > Math.abs(-1)'));
Update
$obj = $col->findOne(array("name"=>"MongoDB"));
$obj["value"] = 2;$col->save($obj);
Delete
$col->remove(array("name" => "MongoDB"));
$obj = $col->findOne();$col->remove($obj);
$col->drop();$db->drop();
Count
$col->count();$col->count(array('x'=>1));
Index 作成$col->ensureIndex( array( "name" => 1 ) );$col->ensureIndex( array( "name" => 1 ,
"count" => -1 ) );
• Index に対応するデータは一意であり、全てのドキュメントで必須である必要がある
使い方[MapReduce]
MapReduce とは?• 大量のサーバ上で分散処理をするために考案された手法
• Key-Value の組み合わせを単純な方法で分散して再計算することによって、複雑な計算に対応する
• Map フェーズと Reduce フェーズの処理を与えてあげるだけで、後の処理はシステムが自動的に分散して行ってくれる
MapReduce とは?• Map– ある大量のデータを、一連の Key-Value の形
式にして、システムに渡す• システム–Map で渡されたデータを、同一の Key で束ねる
• Reduce– システムから渡ってきたデータを加工し、出力する
例:ユーザーごとの買い物金額の合計
• MapReduce を使う必要があるかは謎• そもそも設計も怪しい
データ例名前 品物 金額
hokkai apple 100
hokkai orange 100
onodes bread 100
onodes beef 200
reath book 300
reath pen 100
※名前は実在の人物とは一切関係ありません
Map
Map関数 hokkai=100
hokkai=100
onodes=100
onodes=200
reath=300
reath=100
元データ
元データ
元データ
元データ
元データ
元データ
Reduce
Reduce関数
hokkai=[100,100]
onodes=[100,200]
reath=[100, 300]
hokkai=200
onodes=300
reath=400
MongoDB で MapReduce
• MapReduce に与える Map/Reduce関数を JavaScript で記述
• PHP で使う場合は MongoDB-MapReduce-PHP ライブラリを使うと少し楽– でも処理自体は結局 JavaScript で書かないと
いけない
基本データ$col->insert( array("user" => "hokkai", "item" =>
"apple", "price" => 100 ) );$col->insert( array("user" => "hokkai", "item" =>
"orange", "price" => 100 ) );$col->insert( array("user" => "onodes", "item" =>
"bread", "price" => 100 ) );$col->insert( array("user" => "onodes", "item" =>
"beef", "price" => 200 ) );$col->insert( array("user" => "reath", "item" =>
"book", "price" => 300 ) );$col->insert( array("user" => "reath", "item" =>
"pen", "price" => 100 ) );
Map
$map = <<<MAPfunction() { emit(this.user, this.price);}MAP;
Reduce
$reduce = <<<REDUCEfunction(key, values) { var total = 0; for(var i in values) total +=
values[i]; return total;}REDUCE;
PHP側( insert済みな前提)<?php
require_once('./MongoDB-MapReduce-PHP/lib/MongoMapReduce.php');require_once('./MongoDB-MapReduce-PHP/lib/MongoMapReduceResponse.php');
$mongo = new Mongo();$db = $mongo->selectDB( 'mydb' );$col = $db->selectCollection( 'shop' );// $mapと$reduceは省略$map_reduce = new MongoMapReduce($map, $reduce);$response = $map_reduce->invoke($db, "shop");if ($response->valid()) { foreach($response->getResultSet() as $result) { echo "name: ", $result["_id"] , " / price: ", $result["value"], PHP_ EOL; }}
結果name: hokkai / price: 200name: onodes / price: 300name: reath / price: 400
ほかのデータストアと比較
RDBMS との違い• 分散が楽!– 様々な分散方法を標準搭載– MapReduce
• テーブル定義不要– 動的に構造を付け足したりできる– プログラミング言語の構造に密着
• JOIN はできない– MapReduce でカバー
• トランザクションはない– 銀行のシステムとか作りたいなら RDBMS でいいんじゃね?
KVS との違い• KVS=Key-Value Store–Memcached 、 Tokyo
Cabinet/Tyrant 、 Flared 、 ROMA 、 BigTable、 etc…
• KVS よりは分散は大変– KVS は置くだけで分散できるものが多い
• KVS よりはデータ構造が存在する– KVS は単純に Key-Value の構造しかない(キー
での検索しかできない)–MongoDB は大体 RDBMS に近い設計手法で操
作ができる
CouchDB との違い• 基本的には同じ• まだ比較できるほどの事例が存在しない• PHP で使うなら MongoDB のほうが楽• 若干用語とかが違う
KVS
MongoDB
RDBMS
高速
高機能
まとめ
実用的に MongoDB を PHP で使うなら
• Lithium ( http://li3.rad-dev.org/ )– PHP5.3専用フレームワーク–MongoDB推奨で設計されている–チュートリアルももちろん MongoDB
• CakePHP用 DataSource– http://d.hatena.ne.jp/cakephper/
20100122/1264140610
• 単体ライブラリ–Mongodloid 、 Morph
実際使えるのか?• もちろんレンタルサーバの類では不可• RDBMS より圧倒的に高速なので、高負荷
に耐えれるサービスを作るなら重要• トランザクションが重要になるサービス
では使えない• テーブル定義とか書かなくていいので、立
ち上げ時とか試行錯誤する時とかはものすごく簡単に書ける
日本語の情報が少なくて…• 概念とかは CouchDB関係で調べれば近
いものが出てくる• 情報がないなら自分たちで発信しよう!– CakePHP用 datastore の作者は日本人だし
日本語の情報しか存在しないが、公式に掲載された
• 翻訳も積極的に!
おわり