提 供LOCAL PHP部
PHPとMongoDBで学ぶ次世代データストア佐藤琢哉LOCAL PHP部
自己紹介佐藤琢哉 aka nazo旭川出身 東京在住株式会社RYUS所属(http://ryus.co.jp)3月末までLOCAL PHP部Hatena : nazonetwitter : 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.
ドキュメント指向データベーススキーマがないデータ定義自体が各ドキュメントに入っている
RDBMS行と列にデータを当てはめていくのがRDBMS
ドキュメントの集合ドキュメント指向ID:1名前:hokkai性別:男ID:3名前:reathID:2名前:onodes電話番号:xxx-xxx-xxxxID: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構成ペアDBMaster-Master構成(制限あり)Sharding
なんでMongoDBなの?
日本だとCouchDBのほうが情報が圧倒的に多いのになんでMongoDBとかマイナーそうなのを…
提 供LOCAL PHP部
http://php.net/mongo
そりゃMongoDBしかない!
ちなみに世界的には青:CouchDB赤:MongoDB
使い方[インストール]
インストールいろんなプラットフォームのバイナリが配布されているので好きなのを入れる。
インストールデータフォルダをデフォルトで/data/dbに作るので、面倒であればフォルダを作っておく起動時の設定でもちろん変更可能
インストールmongodを実行するだけで起動面倒な人はinitスクリプトinit.d for MongoDBhttp://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" );
データベースとコレクション
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 );
INSERTPHPの配列がそのままデータとして入る複雑な階層でももちろんそのまま入る1コレクション内の構造が統一されていなくてもいい(ただしインデックスを張る場合はその項目は必須)
INSERT$doc = array( "name" => "Apple",   "color" => "Red",);$col->insert( $doc );$doc = array( "name" => "Beer",   "price" => 300,);$col->insert( $doc );
SELECT1件取得$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を使う必要があるかは謎そもそも設計も怪しい
データ例※名前は実在の人物とは一切関係ありません
Mapreath=300元データMap関数hokkai=100元データonodes=100元データhokkai=100元データ元データonodes=200reath=100元データ
Reducehokkai=[100,100]hokkai=200Reduce関数onodes=[100,200]onodes=300reath=[100, 300]reath=400
MongoDBでMapReduceMapReduceに与える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(vari in values) total += values[i];    return total;}REDUCE;
PHP側(insert済みな前提)<?phprequire_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 StoreMemcached、Tokyo Cabinet/Tyrant、Flared、ROMA、BigTable、etc…KVSよりは分散は大変KVSは置くだけで分散できるものが多いKVSよりはデータ構造が存在するKVSは単純にKey-Valueの構造しかない(キーでの検索しかできない)MongoDBは大体RDBMSに近い設計手法で操作ができる
CouchDBとの違い基本的には同じまだ比較できるほどの事例が存在しないPHPで使うならMongoDBのほうが楽若干用語とかが違う
高速KVSMongoDB高機能RDBMS
まとめ
実用的にMongoDBをPHPで使うならLithium( http://li3.rad-dev.org/)PHP5.3専用フレームワークMongoDB推奨で設計されているチュートリアルももちろんMongoDBCakePHP用DataSourcehttp://d.hatena.ne.jp/cakephper/20100122/1264140610単体ライブラリMongodloid、Morph
実際使えるのか?もちろんレンタルサーバの類では不可RDBMSより圧倒的に高速なので、高負荷に耐えれるサービスを作るなら重要トランザクションが重要になるサービスでは使えないテーブル定義とか書かなくていいので、立ち上げ時とか試行錯誤する時とかはものすごく簡単に書ける
日本語の情報が少なくて…概念とかはCouchDB関係で調べれば近いものが出てくる情報がないなら自分たちで発信しよう!CakePHP用datastoreの作者は日本人だし日本語の情報しか存在しないが、公式に掲載された翻訳も積極的に!
おわり
PHPとMongoDBで学ぶ次世代データストア

PHPとMongoDBで学ぶ次世代データストア