PHP と MySQL で  カジュアルにMapReduce する   @yuya_takeyama
アジェンダ•MapReduce とは• 自作フレームワークMyMR の紹介
お断り (1)ビッグデータの話は  ありません
お断り (2)  業務ではまだやってません
お断り (3) Hadoop 未経験です   ※MongoDB でのMapReduce ならやりました
MapReduce とは
固有名詞として•Google の大規模データ処理フレームワーク•検索インデックスの作成とかに使われている
普通名詞として•Map/Reduce 関数でデータを 処理するプログラミングモデル•   マシンを増やしただけスケール•Hadoop, MongoDB, CouchDB などが主な実装
入力処理の流れ      ↓         Map           ↓        Reduce           ↓          出力
やや厳密な          入力 処理の流れ          ↓              Map                ↓             Shuffle                ↓             Reduc...
Map•入力データを受け取り• 複数の Key/Value ペアを出力
Shuffle•Map による Key/Value を• Key ごとにまとめて出力
Reduce•Shuffle による中間データを• 集約して答えを出力
複数の関数の入出力を経て最終的な答えを出力
文章中の単語の数を数える例 (word count)
入力•to be or not to be
Map   •<"to", 1>      •<"be", 1>      •<"or", 1>      •<"not", 1>      •<"to", 1>      •<"be", 1>
Shuffle   •<"be", [1, 1]>   •<"not", [1]>   •<"or", [1]>   •<"to", [1, 1]>
Reduce  • <"be", 2>  • <"not", 1>  • <"or", 1>  • <"to", 2>
MapReduce の利点•Map も Reduce も並列化すればスケールする•関数型っぽい考え方が活きる※ただし, Hadoop や MongoDB の MapReduce の Map と Reduce は 関数型言語のそれとはやや異なる ...
MongoDB について•通常は MapReduce を並列に実行することができない•   それでも MapReduce は便利•何故か?
スケーラビリティだけじゃない•プログラミングモデルとしての MapReduce にも価値がある•   MongoDB で処理が完結•JS で関数ふたつ書くだけ
MySQL でもMapReduce  したい!!!
というわけで作りました
MyMR   https://github.com/yuya-takeyama/mymr•MySQL を入出力とする• PHP で Map/Reduce を書く• コマンドラインで実行
MyMR による処理の流れ•テーブルからレコードを読む•1 行 1 行に Map (PHP) を適用して  中間テーブルへ•MySQL による Shuffle•その結果に Reduce (PHP) を適用して  出力テーブルへ
に よ る yM RM    文章中の単語の数を数える例 (word count)
use MyMRBuilder;                      Map/Reduce の定義$builder = new Builder;$builder->setInputTable(root@localhost/db/texts...
use MyMRBuilder;                      Map/Reduce の定義$builder = new Builder;$builder->setInputTable(root@localhost/db/texts...
use MyMRBuilder;                      Map/Reduce の定義$builder = new Builder;$builder->setInputTable(root@localhost/db/texts...
use MyMRBuilder;                      Map/Reduce の定義$builder = new Builder;$builder->setInputTable(root@localhost/db/texts...
入力•to be or not to be
Mapfunction ($record, $emitter) {    $words = preg_split(/s+/u,                        $record[text]);    foreach ($words ...
Map       レコードを                       連想配列として受け取るfunction ($record, $emitter) {    $words = preg_split(/s+/u,             ...
Mapfunction ($record, $emitter) {    $words = preg_split(/s+/u,                        $record[text]);    foreach ($words ...
Mapfunction ($record, $emitter) {    $words = preg_split(/s+/u,                        $record[text]);    foreach ($words ...
Reducefunction ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array...
Reduce                 Key      Value の配列function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $...
Reduce                         Value を全て足すfunction ($key, $values) {    $sum = 0;    foreach ($values as $count) {        ...
Reducefunction ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array...
+----+--------------------+Map    | id | text               |       +----+--------------------+       | 1 | to be or not t...
+----+--------------------+Map          | id | text               |             +----+--------------------+             | ...
+----+---------+-------+                            | id | key     | value |Shuffle                      +----+---------+--...
+---------+--------+            | key     | values |Reduce      +---------+--------+            | be      | 1,1    |      ...
+---------+--------+                 | key     | values |Reduce           +---------+--------+                 | be      |...
モチベーション•プログラミングモデルとしてのMapReduce を使いたい•   MySQL を入出力にしたい•LL でサクッとやりたい
モチベーション•プログラミングモデルとしてのMapReduce を使いたい•   MySQL を入出力にしたい•LL でサクッとやりたい       PHP である必要はあまり無い
今後の目標•非同期 INSERT による並列化• Hadoop へのシームレスな移行方法の提供
まとめ•ビッグデータは無くともMapReduce は有効•   MySQL でできたら便利なはず•PHP で書けたら楽しいはず
リンク• MyMR on GitHub  https://github.com/yuya-takeyama/mymr• PHP と MySQL でカジュアルに MapReduce する  http://blog.yuyat.jp/archive...
ご清聴 ありがとうございました
Upcoming SlideShare
Loading in …5
×

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

7,907 views

Published on

Published in: Technology

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

  1. 1. PHP と MySQL で カジュアルにMapReduce する @yuya_takeyama
  2. 2. アジェンダ•MapReduce とは• 自作フレームワークMyMR の紹介
  3. 3. お断り (1)ビッグデータの話は ありません
  4. 4. お断り (2) 業務ではまだやってません
  5. 5. お断り (3) Hadoop 未経験です ※MongoDB でのMapReduce ならやりました
  6. 6. MapReduce とは
  7. 7. 固有名詞として•Google の大規模データ処理フレームワーク•検索インデックスの作成とかに使われている
  8. 8. 普通名詞として•Map/Reduce 関数でデータを 処理するプログラミングモデル• マシンを増やしただけスケール•Hadoop, MongoDB, CouchDB などが主な実装
  9. 9. 入力処理の流れ ↓ Map ↓ Reduce ↓ 出力
  10. 10. やや厳密な 入力 処理の流れ ↓ Map ↓ Shuffle ↓ Reduceより厳密には ↓もっと複雑らしいです 出力
  11. 11. Map•入力データを受け取り• 複数の Key/Value ペアを出力
  12. 12. Shuffle•Map による Key/Value を• Key ごとにまとめて出力
  13. 13. Reduce•Shuffle による中間データを• 集約して答えを出力
  14. 14. 複数の関数の入出力を経て最終的な答えを出力
  15. 15. 文章中の単語の数を数える例 (word count)
  16. 16. 入力•to be or not to be
  17. 17. Map •<"to", 1> •<"be", 1> •<"or", 1> •<"not", 1> •<"to", 1> •<"be", 1>
  18. 18. Shuffle •<"be", [1, 1]> •<"not", [1]> •<"or", [1]> •<"to", [1, 1]>
  19. 19. Reduce • <"be", 2> • <"not", 1> • <"or", 1> • <"to", 2>
  20. 20. MapReduce の利点•Map も Reduce も並列化すればスケールする•関数型っぽい考え方が活きる※ただし, Hadoop や MongoDB の MapReduce の Map と Reduce は 関数型言語のそれとはやや異なる (参照透過でなかったり)• パターンとして共有しやすい※手続き型のバッチ処理と比較して
  21. 21. MongoDB について•通常は MapReduce を並列に実行することができない• それでも MapReduce は便利•何故か?
  22. 22. スケーラビリティだけじゃない•プログラミングモデルとしての MapReduce にも価値がある• MongoDB で処理が完結•JS で関数ふたつ書くだけ
  23. 23. MySQL でもMapReduce したい!!!
  24. 24. というわけで作りました
  25. 25. MyMR https://github.com/yuya-takeyama/mymr•MySQL を入出力とする• PHP で Map/Reduce を書く• コマンドラインで実行
  26. 26. MyMR による処理の流れ•テーブルからレコードを読む•1 行 1 行に Map (PHP) を適用して 中間テーブルへ•MySQL による Shuffle•その結果に Reduce (PHP) を適用して 出力テーブルへ
  27. 27. に よ る yM RM 文章中の単語の数を数える例 (word count)
  28. 28. use MyMRBuilder; Map/Reduce の定義$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;
  29. 29. use MyMRBuilder; Map/Reduce の定義$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;
  30. 30. use MyMRBuilder; Map/Reduce の定義$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);    } この辺が Map});$builder->setReducer(function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array(count => $sum);});return $builder;
  31. 31. use MyMRBuilder; Map/Reduce の定義$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); この辺が Reduce});return $builder;
  32. 32. 入力•to be or not to be
  33. 33. Mapfunction ($record, $emitter) {    $words = preg_split(/s+/u, $record[text]);    foreach ($words as $word) {        $emitter->emit($word, 1);    }}
  34. 34. Map レコードを 連想配列として受け取るfunction ($record, $emitter) {    $words = preg_split(/s+/u, $record[text]);    foreach ($words as $word) {        $emitter->emit($word, 1);    }}
  35. 35. Mapfunction ($record, $emitter) {    $words = preg_split(/s+/u, $record[text]);    foreach ($words as $word) {        $emitter->emit($word, 1);    }} text カラム内の 文字列をスペースで分割
  36. 36. Mapfunction ($record, $emitter) {    $words = preg_split(/s+/u, $record[text]);    foreach ($words as $word) {        $emitter->emit($word, 1);    }} Key/Value のペアとして 中間テーブルに INSERT
  37. 37. Reducefunction ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array(count => $sum);}
  38. 38. Reduce Key Value の配列function ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array(count => $sum);}
  39. 39. Reduce Value を全て足すfunction ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array(count => $sum);}
  40. 40. Reducefunction ($key, $values) {    $sum = 0;    foreach ($values as $count) {        $sum += $count;    }    return array(count => $sum);} 返り値の連想配列を レコードとして INSERT
  41. 41. +----+--------------------+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 | +----+---------+-------+
  42. 42. +----+--------------------+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 value には JSON で入れるので | 1 | | 5 | to 構造化データも使用可能 | 1 | | 6 | be | 1 | +----+---------+-------+
  43. 43. +----+---------+-------+ | id | key | value |Shuffle +----+---------+-------+ | 1 | to | 2 | be | 1 | 1 | | | 3 | or | 1 | | 4 | not | 1 | | 5 | to | 1 | | 6 | be | 1 | +----+---------+-------+ ↓ キーで GROUP BY して ↓SELECT ↓ 値は GROUP_CONCAT ↓ `key`, +---------+--------+ GROUP_CONCAT(`value`) | key | values |FROM +---------+--------+ `中間テーブル` | be | 1,1 | | not | 1 |GROUP BY | or | 1 | `key` | to | 1,1 | +---------+--------+
  44. 44. +---------+--------+ | key | values |Reduce +---------+--------+ | be | 1,1 | | not | 1 | | or | 1 | | to | 1,1 | +---------+--------+ ↓ キーと値の配列を Reduce へ ↓ +----+---------+-------+ | id | key | count | +----+---------+-------+ | 1 | be | 2 | | 2 | not | 1 | | 3 | or | 1 | | 4 | to | 2 | +----+---------+-------+
  45. 45. +---------+--------+ | key | values |Reduce +---------+--------+ | be | 1,1 | | not | 1 | | or | 1 | 実際にはデリミタとして改行を使用| to | 1,1 | +---------+--------+ 改行区切りの JSON になる ↓ キーと値の配列を Reduce へ ↓ +----+---------+-------+ | id | key | count | +----+---------+-------+ | 1 | be | 2 | | 2 | not | 1 | | 3 | or | 1 | | 4 | to | 2 | +----+---------+-------+
  46. 46. モチベーション•プログラミングモデルとしてのMapReduce を使いたい• MySQL を入出力にしたい•LL でサクッとやりたい
  47. 47. モチベーション•プログラミングモデルとしてのMapReduce を使いたい• MySQL を入出力にしたい•LL でサクッとやりたい PHP である必要はあまり無い
  48. 48. 今後の目標•非同期 INSERT による並列化• Hadoop へのシームレスな移行方法の提供
  49. 49. まとめ•ビッグデータは無くともMapReduce は有効• MySQL でできたら便利なはず•PHP で書けたら楽しいはず
  50. 50. リンク• MyMR on GitHub https://github.com/yuya-takeyama/mymr• PHP と MySQL でカジュアルに MapReduce する http://blog.yuyat.jp/archives/1706• もっとカジュアルに PHP と MySQL で MapReduce する http://blog.yuyat.jp/archives/1853
  51. 51. ご清聴 ありがとうございました

×