スライド1: PHP と MongoDB で学ぶ次世代データストア佐藤琢哉LOCAL PHP 部
スライド2:
スライド3: 突然ですが
スライド4: 4月から札幌市民になります!!!!!
スライド5: 友達が少ないので皆さん遊んでやってください
スライド6: • MongoDB って何?• 使い方• 他の DBMS との比較• MapReduce• まとめアジェンダ
スライド7: そもそも何の話?
スライド8: MongoDB すごいよ!
スライド9: MongoDB って何?
スライド10: http://www.mongodb.org/
スライド11: MongoDB (from "humongous") is a scalable, highperformance,open source, schema-free, documentorienteddatabase.
スライド12: ドキュメント指向データベース• スキーマがない• データ定義自体が各ドキュメントに入っている
スライド13: RDBMSID 名前 年齢 性別 住所行と列にデータを当てはめていくのがRDBMS
スライド14: ID : 1名前: hokkai性別:男ドキュメント指向ID : 2名前: onodes電話番号: xxx-xxx-xxxxドキュメントの集合ID : 3名前: reathID : 4名前: riafライブラリ: rhaco※ 名前は実在の人物とは一切関係ありません
スライド15: AGPL ライセンス• Web からのみアクセスするものでもソースコードを公開しないといけない GPL• 普通の GPL は、 Web サイトとして使う分にはプログラムを配布するわけじゃないからソースコード公開する必要がないが、それが気にくわないために作られたライセンス
スライド16: AGPL ライセンス• MongoDB 自体をカスタマイズするなら例え Web サイト内部だけで使ってても公開要求に応じないと駄目よー• 各言語からアクセスするドライバはApache License だから大丈夫よー• 社内からしかアクセスできないような場所で使う分には平気よー
スライド17: 特長
スライド18: データを BSON で保存• BSON is a binary-encoded serialization of JSONlikedocuments• { hoge: "fuga", foo: [bar, baz] }• 構造が自由• XML データベースが JSON になったような感じ• JSON なので操作も簡単• ちょっとした構造で JOIN とかする必要がない
スライド19: JavaScript 処理系内蔵• MongoDB 単体で JavaScript でデータを操作することが可能• JSON で記録されたデータをそのまま処理できる• ストアドプロシージャ的な使い方• MapReduce
スライド20: • MapReduce 搭載• Master-Slave 構成スケーラブル• ペア DB• Master-Master 構成(制限あり)• Sharding
スライド21: なんで MongoDB なの?
スライド22: 日本だと CouchDB のほうが情報が圧倒的に多いのになんで MongoDBとかマイナーそうなのを…
スライド23: 提 供LOCAL PHP 部
スライド24: http://php.net/mongo
スライド25: そりゃ MongoDB しかない!
スライド26: ちなみに世界的には青: CouchDB赤: MongoDB
スライド27: 使い方[ インストール ]
スライド28: インストール• いろんなプラットフォームのバイナリが配布されているので好きなのを入れる。
スライド29: インストール• データフォルダをデフォルトで /data/dbに作るので、面倒であればフォルダを作っておく• 起動時の設定でもちろん変更可能
スライド30: インストール• mongod を実行するだけで起動• 面倒な人は init スクリプト– init.d for MongoDB– http://gist.github.com/232227
スライド31: • pecl install mongoインストール• あと php.ini に extension=mongo.so と書くだけ– PHPer 歓喜
スライド32: 使い方[PHP コード ]
スライド33: 接続• $mongo = new Mongo();• $mongo = newMongo("example.com:65432");
スライド34: データベースとコレクションの取得• $db = $mongo->selectDB( "dbname" );• $col = $db->selectCollection( "collectionname" );
スライド35: データベースとコレクション
スライド36: 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 );
スライド37: INSERT• PHP の配列がそのままデータとして入る• 複雑な階層でももちろんそのまま入る• 1コレクション内の構造が統一されていなくてもいい(ただしインデックスを張る場合はその項目は必須)
スライド38: INSERT$doc = array( "name" => "Apple","color" => "Red",);$col->insert( $doc );$doc = array( "name" => "Beer","price" => 300,);$col->insert( $doc );
スライド39: • 1件取得SELECT$obj = $col->findOne();• 条件指定取得$obj = $col->findOne(array("name"=>"MongoDB"));• 全件取得$cursor = $col->find();
スライド40: SELECT• $cursor = $col->find(array('num' =>array('$gt' => 1)));• $cursor = $col->find(array('name' => newMongoRegex('/ba/i')));• $cursor = $col->find(array('$where' =>'this.num > Math.abs(-1)'));
スライド41: Update$obj = $col->findOne(array("name"=>"MongoDB"));$obj["value"] = 2;$col->save($obj);
スライド42: Delete$col->remove(array("name" =>"MongoDB"));$obj = $col->findOne();$col->remove($obj);$col->drop();$db->drop();
スライド43: $col->count();Count$col->count(array('x'=>1));
スライド44: Index 作成$col->ensureIndex( array( "name" => 1 ) );$col->ensureIndex( array( "name" => 1 ,"count" => -1 ) );• Index に対応するデータは一意であり、全てのドキュメントで必須である必要がある
スライド45: 使い方[MapReduce]
スライド46: MapReduce とは?• 大量のサーバ上で分散処理をするために考案された手法• Key-Value の組み合わせを単純な方法で分散して再計算することによって、複雑な計算に対応する• Map フェーズと Reduce フェーズの処理を与えてあげるだけで、後の処理はシステムが自動的に分散して行ってくれる
スライド47: MapReduce とは?• Map– ある大量のデータを、一連の Key-Value の形式にして、システムに渡す• システム– Map で渡されたデータを、同一の Key で束ねる• Reduce– システムから渡ってきたデータを加工し、出力する
スライド48: 例:ユーザーごとの買い物金額の合計• MapReduce を使う必要があるかは謎• そもそも設計も怪しい
スライド49: データ例名前 品物 金額hokkai apple 100hokkai orange 100onodes bread 100onodes beef 200reath book 300reath pen 100※ 名前は実在の人物とは一切関係ありません
スライド50: 元データ元データ元データ元データ元データ元データMapMap 関数reath=300hokkai=100onodes=100hokkai=100onodes=200reath=100
スライド51: hokkai=[100,100]onodes=[100,200]reath=[100, 300]ReduceReduce 関数hokkai=200onodes=300reath=400
スライド52: MongoDB で MapReduce• MapReduce に与える Map/Reduce 関数をJavaScript で記述• PHP で使う場合は MongoDB-MapReduce-PHP ライブラリを使うと少し楽– でも処理自体は結局 JavaScript で書かないといけない
スライド53: 基本データ$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 ) );
スライド54: $map = <<<MAPfunction() {}Mapemit(this.user, this.price);MAP;
スライド55: $reduce = <<<REDUCEfunction(key, values) {}var total = 0;Reducefor(var i in values) total += values[i];return total;REDUCE;
スライド56: <?phpPHP 側( insert 済みな前提)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;}}
スライド57: 結果name: hokkai / price: 200name: onodes / price: 300name: reath / price: 400
スライド58: ほかのデータストアと比較
スライド59: RDBMS との違い• 分散が楽!– 様々な分散方法を標準搭載– MapReduce• テーブル定義不要– 動的に構造を付け足したりできる– プログラミング言語の構造に密着• JOIN はできない– MapReduce でカバー• トランザクションはない– 銀行のシステムとか作りたいなら RDBMS でいいんじゃね?
スライド60: KVS との違い• KVS=Key-Value Store– Memcached 、 TokyoCabinet/Tyrant 、 Flared 、 ROMA 、 BigTable、 etc…• KVS よりは分散は大変– KVS は置くだけで分散できるものが多い• KVS よりはデータ構造が存在する– KVS は単純に Key-Value の構造しかない(キーでの検索しかできない)– MongoDB は大体 RDBMS に近い設計手法で操作ができる
スライド61: • 基本的には同じCouchDB との違い• まだ比較できるほどの事例が存在しない• PHP で使うなら MongoDB のほうが楽• 若干用語とかが違う
スライド62: 高速高機能KVSMongoDBRDBMS
スライド63: まとめ
スライド64: 実用的に MongoDB を PHP で使うなら• Lithium ( http://li3.rad-dev.org/ )– PHP5.3 専用フレームワーク– MongoDB 推奨で設計されている– チュートリアルももちろん MongoDB• CakePHP 用 DataSource– http://d.hatena.ne.jp/cakephper/20100122/1264140610• 単体ライブラリ– Mongodloid 、 Morph
スライド65: 実際使えるのか?• もちろんレンタルサーバの類では不可• RDBMS より圧倒的に高速なので、高負荷に耐えれるサービスを作るなら重要• トランザクションが重要になるサービスでは使えない• テーブル定義とか書かなくていいので、立ち上げ時とか試行錯誤する時とかはものすごく簡単に書ける
スライド66: 日本語の情報が少なくて …• 概念とかは CouchDB 関係で調べれば近いものが出てくる• 情報がないなら自分たちで発信しよう!– CakePHP 用 datastore の作者は日本人だし日本語の情報しか存在しないが、公式に掲載された• 翻訳も積極的に!
スライド67: おわり