php と mysql でカジュアルに mapreduce する

51
PHP と MySQL で カジュアルに MapReduce する @yuya_takeyama

Upload: yuya-takeyama

Post on 13-Jan-2015

6.483 views

Category:

Technology


2 download

DESCRIPTION

 

TRANSCRIPT

Page 1: PHP と MySQL でカジュアルに MapReduce する

PHP と MySQL でカジュアルに

MapReduce する

@yuya_takeyama

Page 2: PHP と MySQL でカジュアルに MapReduce する

アジェンダ

•MapReduce とは

•自作フレームワークMyMR の紹介

Page 3: PHP と MySQL でカジュアルに MapReduce する

お断り (1)

ビッグデータの話はありません

Page 4: PHP と MySQL でカジュアルに MapReduce する

お断り (2)

業務ではまだやってません

Page 5: PHP と MySQL でカジュアルに MapReduce する

お断り (3)

Hadoop未経験です※MongoDB での

MapReduce ならやりました

Page 6: PHP と MySQL でカジュアルに MapReduce する

MapReduce とは

Page 7: PHP と MySQL でカジュアルに MapReduce する

固有名詞として

•Google の大規模データ処理フレームワーク

•検索インデックスの作成とかに使われている

Page 8: PHP と MySQL でカジュアルに MapReduce する

普通名詞として•Map/Reduce 関数でデータを処理するプログラミングモデル

•マシンを増やしただけスケール•Hadoop, MongoDB, CouchDB などが主な実装

Page 9: PHP と MySQL でカジュアルに MapReduce する

処理の流れ 入力↓

Map↓

Reduce↓出力

Page 10: PHP と MySQL でカジュアルに MapReduce する

処理の流れ入力↓

Map↓

Shuffle↓

Reduce↓出力

やや厳密な

より厳密にはもっと複雑らしいです

Page 11: PHP と MySQL でカジュアルに MapReduce する

Map

•入力データを受け取り•複数の Key/Value ペアを出力

Page 12: PHP と MySQL でカジュアルに MapReduce する

Shuffle

•Map による Key/Value を

•Key ごとにまとめて出力

Page 13: PHP と MySQL でカジュアルに MapReduce する

Reduce

•Shuffle による中間データを•集約して答えを出力

Page 14: PHP と MySQL でカジュアルに MapReduce する

複数の関数の入出力を経て最終的な答えを出力

Page 15: PHP と MySQL でカジュアルに MapReduce する

文章中の単語の数を数える例(word count)

Page 16: PHP と MySQL でカジュアルに MapReduce する

入力

•to be or not to be

Page 17: PHP と MySQL でカジュアルに MapReduce する

Map •<"to", 1>

•<"be", 1>

•<"or", 1>

•<"not", 1>

•<"to", 1>

•<"be", 1>

Page 18: PHP と MySQL でカジュアルに MapReduce する

Shuffle•<"be", [1, 1]>

•<"not", [1]>

•<"or", [1]>

•<"to", [1, 1]>

Page 19: PHP と MySQL でカジュアルに MapReduce する

Reduce•<"be", 2>

•<"not", 1>

•<"or", 1>

•<"to", 2>

Page 20: PHP と MySQL でカジュアルに MapReduce する

MapReduce の利点•Map も Reduce も並列化すればスケールする

•関数型っぽい考え方が活きる※ただし, Hadoop や MongoDB の MapReduce の Map と Reduce は 関数型言語のそれとはやや異なる (参照透過でなかったり)

•パターンとして共有しやすい※手続き型のバッチ処理と比較して

Page 21: PHP と MySQL でカジュアルに MapReduce する

MongoDB について

•通常は MapReduce を並列に実行することができない

•それでも MapReduce は便利

•何故か?

Page 22: PHP と MySQL でカジュアルに MapReduce する

スケーラビリティだけじゃない

•プログラミングモデルとしてのMapReduce にも価値がある

•MongoDB で処理が完結

•JS で関数ふたつ書くだけ

Page 23: PHP と MySQL でカジュアルに MapReduce する

MySQL でもMapReduce

したい!!!

Page 24: PHP と MySQL でカジュアルに MapReduce する

というわけで作りました

Page 25: PHP と MySQL でカジュアルに MapReduce する

MyMR

•MySQL を入出力とする

•PHP で Map/Reduce を書く

•コマンドラインで実行

https://github.com/yuya-takeyama/mymr

Page 26: PHP と MySQL でカジュアルに MapReduce する

MyMR による処理の流れ•テーブルからレコードを読む•1 行 1 行に Map (PHP) を適用して中間テーブルへ

•MySQL による Shuffle

•その結果に Reduce (PHP) を適用して出力テーブルへ

Page 27: PHP と MySQL でカジュアルに MapReduce する

文章中の単語の数を数える例(word count)

MyMR による

Page 28: PHP と MySQL でカジュアルに MapReduce する

use \MyMR\Builder;

$builder = new Builder;

$builder->setInputTable('root@localhost/db/texts');$builder->setOutputTable('root@localhost/db/word_counts');

$builder->setMapper(function ($record, $emitter) {    $words = preg_split('/\s+/u', $record['text']);    foreach ($words as $word) {        $emitter->emit($word, 1);    }});

$builder->setReducer(function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array('count' => $sum);});

return $builder;

Map/Reduce の定義

Page 29: PHP と MySQL でカジュアルに MapReduce する

use \MyMR\Builder;

$builder = new Builder;

$builder->setInputTable('root@localhost/db/texts');$builder->setOutputTable('root@localhost/db/word_counts');

$builder->setMapper(function ($record, $emitter) {    $words = preg_split('/\s+/u', $record['text']);    foreach ($words as $word) {        $emitter->emit($word, 1);    }});

$builder->setReducer(function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array('count' => $sum);});

return $builder;

Map/Reduce の定義

入出力テーブルの指定

Page 30: PHP と MySQL でカジュアルに MapReduce する

use \MyMR\Builder;

$builder = new Builder;

$builder->setInputTable('root@localhost/db/texts');$builder->setOutputTable('root@localhost/db/word_counts');

$builder->setMapper(function ($record, $emitter) {    $words = preg_split('/\s+/u', $record['text']);    foreach ($words as $word) {        $emitter->emit($word, 1);    }});

$builder->setReducer(function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array('count' => $sum);});

return $builder;

Map/Reduce の定義

この辺が Map

Page 31: PHP と MySQL でカジュアルに MapReduce する

use \MyMR\Builder;

$builder = new Builder;

$builder->setInputTable('root@localhost/db/texts');$builder->setOutputTable('root@localhost/db/word_counts');

$builder->setMapper(function ($record, $emitter) {    $words = preg_split('/\s+/u', $record['text']);    foreach ($words as $word) {        $emitter->emit($word, 1);    }});

$builder->setReducer(function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array('count' => $sum);});

return $builder;

Map/Reduce の定義

この辺が Reduce

Page 32: PHP と MySQL でカジュアルに MapReduce する

入力

•to be or not to be

Page 33: PHP と MySQL でカジュアルに MapReduce する

function ($record, $emitter) {    $words = preg_split('/\s+/u', $record['text']);    foreach ($words as $word) {        $emitter->emit($word, 1);    }}

Map

Page 34: PHP と MySQL でカジュアルに MapReduce する

function ($record, $emitter) {    $words = preg_split('/\s+/u', $record['text']);    foreach ($words as $word) {        $emitter->emit($word, 1);    }}

レコードを連想配列として受け取る

Map

Page 35: PHP と MySQL でカジュアルに MapReduce する

function ($record, $emitter) {    $words = preg_split('/\s+/u', $record['text']);    foreach ($words as $word) {        $emitter->emit($word, 1);    }} text カラム内の

文字列をスペースで分割

Map

Page 36: PHP と MySQL でカジュアルに MapReduce する

function ($record, $emitter) {    $words = preg_split('/\s+/u', $record['text']);    foreach ($words as $word) {        $emitter->emit($word, 1);    }}

Key/Value のペアとして中間テーブルに INSERT

Map

Page 37: PHP と MySQL でカジュアルに MapReduce する

function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array('count' => $sum);}

Reduce

Page 38: PHP と MySQL でカジュアルに MapReduce する

function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array('count' => $sum);}

ReduceKey Value の配列

Page 39: PHP と MySQL でカジュアルに MapReduce する

function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array('count' => $sum);}

ReduceValue を全て足す

Page 40: PHP と MySQL でカジュアルに MapReduce する

function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array('count' => $sum);}

Reduce

返り値の連想配列をレコードとして INSERT

Page 41: PHP と MySQL でカジュアルに MapReduce する

Map+----+--------------------+| id | text |+----+--------------------+| 1 | to be or not to be |+----+--------------------+

↓ レコードを連想配列として Map へ ↓+----+---------+-------+ | id | key | value | +----+---------+-------+ | 1 | to | 1 | | 2 | be | 1 | | 3 | or | 1 | | 4 | not | 1 | | 5 | to | 1 | | 6 | be | 1 | +----+---------+-------+

Page 42: PHP と MySQL でカジュアルに MapReduce する

Map+----+--------------------+| id | text |+----+--------------------+| 1 | to be or not to be |+----+--------------------+

↓ レコードを連想配列として Map へ ↓+----+---------+-------+ | id | key | value | +----+---------+-------+ | 1 | to | 1 | | 2 | be | 1 | | 3 | or | 1 | | 4 | not | 1 | | 5 | to | 1 | | 6 | be | 1 | +----+---------+-------+

value には JSON で入れるので構造化データも使用可能

Page 43: PHP と MySQL でカジュアルに MapReduce する

Shuffle

↓ キーで GROUP BY して ↓↓ 値は GROUP_CONCAT ↓

+---------+--------+| key | values |+---------+--------+| be | 1,1 || not | 1 || or | 1 || to | 1,1 |+---------+--------+

+----+---------+-------+ | id | key | value | +----+---------+-------+ | 1 | to | 1 | | 2 | be | 1 | | 3 | or | 1 | | 4 | not | 1 | | 5 | to | 1 | | 6 | be | 1 | +----+---------+-------+

SELECT `key`, GROUP_CONCAT(`value`)FROM `中間テーブル`

GROUP BY `key`

Page 44: PHP と MySQL でカジュアルに MapReduce する

Reduce

↓ キーと値の配列を Reduce へ ↓

+---------+--------+| key | values |+---------+--------+| be | 1,1 || not | 1 || or | 1 || to | 1,1 |+---------+--------+

+----+---------+-------+| id | key | count |+----+---------+-------+| 1 | be | 2 || 2 | not | 1 || 3 | or | 1 || 4 | to | 2 |+----+---------+-------+

Page 45: PHP と MySQL でカジュアルに MapReduce する

Reduce

↓ キーと値の配列を Reduce へ ↓

+---------+--------+| key | values |+---------+--------+| be | 1,1 || not | 1 || or | 1 || to | 1,1 |+---------+--------+

+----+---------+-------+| id | key | count |+----+---------+-------+| 1 | be | 2 || 2 | not | 1 || 3 | or | 1 || 4 | to | 2 |+----+---------+-------+

実際にはデリミタとして改行を使用改行区切りの JSON になる

Page 46: PHP と MySQL でカジュアルに MapReduce する

モチベーション

•プログラミングモデルとしてのMapReduce を使いたい

•MySQL を入出力にしたい

•LL でサクッとやりたい

Page 47: PHP と MySQL でカジュアルに MapReduce する

モチベーション

•プログラミングモデルとしてのMapReduce を使いたい

•MySQL を入出力にしたい

•LL でサクッとやりたいPHP である必要はあまり無い

Page 48: PHP と MySQL でカジュアルに MapReduce する

今後の目標

•非同期 INSERT による並列化•Hadoop へのシームレスな移行方法の提供

Page 49: PHP と MySQL でカジュアルに MapReduce する

まとめ

•ビッグデータは無くともMapReduce は有効

•MySQL でできたら便利なはず

•PHP で書けたら楽しいはず

Page 50: PHP と MySQL でカジュアルに MapReduce する

リンク

• MyMR on GitHubhttps://github.com/yuya-takeyama/mymr

• PHP と MySQL でカジュアルに MapReduce するhttp://blog.yuyat.jp/archives/1706

• もっとカジュアルに PHP と MySQL で MapReduce するhttp://blog.yuyat.jp/archives/1853

Page 51: PHP と MySQL でカジュアルに MapReduce する

ご清聴ありがとうございました