SlideShare a Scribd company logo
PHP と MySQL で
  カジュアルに
MapReduce する

   @yuya_takeyama
アジェンダ

•MapReduce とは

• 自作フレームワーク
MyMR の紹介
お断り (1)

ビッグデータの話は
  ありません
お断り (2)

  業務では
まだやってません
お断り (3)

 Hadoop
 未経験です
   ※MongoDB での
MapReduce ならやりました
MapReduce とは
固有名詞として

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

•
検索インデックスの作成とかに
使われている
普通名詞として
•Map/Reduce 関数でデータを
 処理するプログラミングモデル

•   マシンを増やしただけスケール

•Hadoop, MongoDB,
 CouchDB などが主な実装
入力
処理の流れ      ↓
         Map
           ↓
        Reduce
           ↓
          出力
やや厳密な          入力
 処理の流れ          ↓
              Map
                ↓
             Shuffle
                ↓
             Reduce
より厳密には          ↓
もっと複雑らしいです
               出力
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 R
M
    文章中の
単語の数を数える例
 (word count)
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;
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;
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;
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;
入力


•to be or not to be
Map

function ($record, $emitter) {
    $words = preg_split('/s+/u',
                        $record['text']);
    foreach ($words as $word) {
        $emitter->emit($word, 1);
    }
}
Map       レコードを
                       連想配列として受け取る

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

function ($record, $emitter) {
    $words = preg_split('/s+/u',
                        $record['text']);
    foreach ($words as $word) {
        $emitter->emit($word, 1);
    }
}                         text カラム内の
                       文字列をスペースで分割
Map

function ($record, $emitter) {
    $words = preg_split('/s+/u',
                        $record['text']);
    foreach ($words as $word) {
        $emitter->emit($word, 1);
    }
}
                    Key/Value のペアとして
                    中間テーブルに INSERT
Reduce
function ($key, $values) {
    $sum = 0;
    foreach ($values as $count) {
        $sum += $count;
    }
    return array('count' => $sum);
}
Reduce
                 Key      Value の配列

function ($key, $values) {
    $sum = 0;
    foreach ($values as $count) {
        $sum += $count;
    }
    return array('count' => $sum);
}
Reduce
                         Value を全て足す
function ($key, $values) {
    $sum = 0;
    foreach ($values as $count) {
        $sum += $count;
    }
    return array('count' => $sum);
}
Reduce
function ($key, $values) {
    $sum = 0;
    foreach ($values as $count) {
        $sum += $count;
    }
    return array('count' => $sum);
}
                     返り値の連想配列を
                    レコードとして INSERT
+----+--------------------+

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     |
        +----+---------+-------+
+----+--------------------+

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     |
               +----+---------+-------+
+----+---------+-------+
                            | 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    |
                              +---------+--------+
+---------+--------+
            | 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 |
           +----+---------+-------+
+---------+--------+
                 | 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 |
                +----+---------+-------+
モチベーション

•
プログラミングモデルとしての
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/archives/1706

• もっとカジュアルに PHP と MySQL で MapReduce する
  http://blog.yuyat.jp/archives/1853
ご清聴
 ありがとう
ございました

More Related Content

Similar to PHP と MySQL でカジュアルに MapReduce する (20)

PPTX
TinyMapReduce on ruby
Kazuki MATSUMOTO
 
PDF
Mongodb 紹介
Ryo Matsumura
 
PPTX
BPStudy32 CouchDB 再入門
Yohei Sasaki
 
PDF
Data-Intensive Text Processing with MapReduce ch4
Sho Shimauchi
 
PDF
"Programming Hive" Reading #1
moai kids
 
PDF
OSC2011 Tokyo/Spring Hadoop入門
Shinichi YAMASHITA
 
PDF
削除フラグのはなし
Shigetaka Yachi
 
PDF
MongoDB2.2の新機能
Shoken Fujisaki
 
PDF
Random partionerのデータモデリング
2t3
 
PDF
MapReduceによる大規模データ処理 at Yahoo! JAPAN
Yahoo!デベロッパーネットワーク
 
PDF
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみました
Etsuji Nakai
 
PDF
MongoDBざっくり解説
知教 本間
 
PDF
Introduction to MongoDB
moai kids
 
PDF
【第3回初心者勉強会】データベースを使おう
Shuhei Iitsuka
 
PDF
20110517 okuyama ソーシャルメディアが育てた技術勉強会
Takahiro Iwase
 
PDF
20120831 mongoid
Takeshi AKIMA
 
PDF
B33 Super HadoopでRockなR&D by 平間大輔
Insight Technology, Inc.
 
PDF
Apache Drill: Rethinking SQL for Big data – Don’t Compromise on Flexibility o...
MapR Technologies Japan
 
PDF
Programming in Scala Chapter 17 Collections
Joongjin Bae
 
KEY
はじめてのCouch db
Eiji Kuroda
 
TinyMapReduce on ruby
Kazuki MATSUMOTO
 
Mongodb 紹介
Ryo Matsumura
 
BPStudy32 CouchDB 再入門
Yohei Sasaki
 
Data-Intensive Text Processing with MapReduce ch4
Sho Shimauchi
 
"Programming Hive" Reading #1
moai kids
 
OSC2011 Tokyo/Spring Hadoop入門
Shinichi YAMASHITA
 
削除フラグのはなし
Shigetaka Yachi
 
MongoDB2.2の新機能
Shoken Fujisaki
 
Random partionerのデータモデリング
2t3
 
MapReduceによる大規模データ処理 at Yahoo! JAPAN
Yahoo!デベロッパーネットワーク
 
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみました
Etsuji Nakai
 
MongoDBざっくり解説
知教 本間
 
Introduction to MongoDB
moai kids
 
【第3回初心者勉強会】データベースを使おう
Shuhei Iitsuka
 
20110517 okuyama ソーシャルメディアが育てた技術勉強会
Takahiro Iwase
 
20120831 mongoid
Takeshi AKIMA
 
B33 Super HadoopでRockなR&D by 平間大輔
Insight Technology, Inc.
 
Apache Drill: Rethinking SQL for Big data – Don’t Compromise on Flexibility o...
MapR Technologies Japan
 
Programming in Scala Chapter 17 Collections
Joongjin Bae
 
はじめてのCouch db
Eiji Kuroda
 

More from Yuya Takeyama (14)

PDF
5分でわかる? 関数型 PHP の潮流
Yuya Takeyama
 
PDF
Good Parts of PHP and the UNIX Philosophy
Yuya Takeyama
 
PDF
Reactor Pattern and React
Yuya Takeyama
 
PDF
PHPUnit でテスト駆動開発を始めよう
Yuya Takeyama
 
PDF
MySQL 入門的なはなし
Yuya Takeyama
 
PDF
HashTable と HashDos
Yuya Takeyama
 
PDF
Proposal for xSpep BDD Framework for PHP
Yuya Takeyama
 
PDF
Building Development Environment with php-build and phpenv
Yuya Takeyama
 
PDF
PHPUnit でよりよくテストを書くために
Yuya Takeyama
 
PDF
Making DSL with []
Yuya Takeyama
 
PDF
LIMIT 付きで UPDATE を行うと何故怒られるか
Yuya Takeyama
 
PDF
GOOS #1
Yuya Takeyama
 
PDF
Ruby 同好会宣言
Yuya Takeyama
 
ODP
第一回 社内勉強会 PHP Application Security Checklist に学ぶ PHP セキュリティ (Excerpt)
Yuya Takeyama
 
5分でわかる? 関数型 PHP の潮流
Yuya Takeyama
 
Good Parts of PHP and the UNIX Philosophy
Yuya Takeyama
 
Reactor Pattern and React
Yuya Takeyama
 
PHPUnit でテスト駆動開発を始めよう
Yuya Takeyama
 
MySQL 入門的なはなし
Yuya Takeyama
 
HashTable と HashDos
Yuya Takeyama
 
Proposal for xSpep BDD Framework for PHP
Yuya Takeyama
 
Building Development Environment with php-build and phpenv
Yuya Takeyama
 
PHPUnit でよりよくテストを書くために
Yuya Takeyama
 
Making DSL with []
Yuya Takeyama
 
LIMIT 付きで UPDATE を行うと何故怒られるか
Yuya Takeyama
 
GOOS #1
Yuya Takeyama
 
Ruby 同好会宣言
Yuya Takeyama
 
第一回 社内勉強会 PHP Application Security Checklist に学ぶ PHP セキュリティ (Excerpt)
Yuya Takeyama
 
Ad

Recently uploaded (10)

PDF
生成AIパネルトーク(Interop25Tokyo APPS JAPAN M1-07,M2-07 嶋ポジショントーク)
嶋 是一 (Yoshikazu SHIMA)
 
PDF
20250630_aws_reinforce_2025_aws_sheild_network_security_director
uedayuki
 
PDF
プライバシ保護のためのインターネットアーキテクチャの進化 (2025-07-11)
Jun Kurihara
 
PDF
人気ブロックチェーン基盤「Hyperledger Fabric」最新版を動かしてみた!
LFDT Tokyo Meetup
 
PDF
[Hardening Designers Confernece 2025]ランサムウェアでの見えざるログ・見えるログ
kataware
 
PDF
SIG-AUDIO 2025 Vol.02 オンラインセミナー SIG-Audioプレゼン資料_オーディオプラグイン開発_塩澤達矢.pdf
IGDA Japan SIG-Audio
 
PDF
ABC2025S LT講演「世界の窓から Androidこんにちは2025」アプリ自動生成の将来?ロボティクスの夢再び?
嶋 是一 (Yoshikazu SHIMA)
 
PDF
20250710_Devinで切り拓くDB革命_〜価値創出に集中せよ〜.pdf
Masaki Yamakawa
 
PDF
Hyperledger Fabric公式サンプル fabric-samples徹底解説
LFDT Tokyo Meetup
 
PDF
Hyperledger Fabric最新v3.x系での機能強化、変更点にキャッチアップ!
LFDT Tokyo Meetup
 
生成AIパネルトーク(Interop25Tokyo APPS JAPAN M1-07,M2-07 嶋ポジショントーク)
嶋 是一 (Yoshikazu SHIMA)
 
20250630_aws_reinforce_2025_aws_sheild_network_security_director
uedayuki
 
プライバシ保護のためのインターネットアーキテクチャの進化 (2025-07-11)
Jun Kurihara
 
人気ブロックチェーン基盤「Hyperledger Fabric」最新版を動かしてみた!
LFDT Tokyo Meetup
 
[Hardening Designers Confernece 2025]ランサムウェアでの見えざるログ・見えるログ
kataware
 
SIG-AUDIO 2025 Vol.02 オンラインセミナー SIG-Audioプレゼン資料_オーディオプラグイン開発_塩澤達矢.pdf
IGDA Japan SIG-Audio
 
ABC2025S LT講演「世界の窓から Androidこんにちは2025」アプリ自動生成の将来?ロボティクスの夢再び?
嶋 是一 (Yoshikazu SHIMA)
 
20250710_Devinで切り拓くDB革命_〜価値創出に集中せよ〜.pdf
Masaki Yamakawa
 
Hyperledger Fabric公式サンプル fabric-samples徹底解説
LFDT Tokyo Meetup
 
Hyperledger Fabric最新v3.x系での機能強化、変更点にキャッチアップ!
LFDT Tokyo Meetup
 
Ad

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

  • 1. PHP と MySQL で カジュアルに MapReduce する @yuya_takeyama
  • 4. お断り (2) 業務では まだやってません
  • 5. お断り (3) Hadoop 未経験です ※MongoDB での MapReduce ならやりました
  • 8. 普通名詞として •Map/Reduce 関数でデータを 処理するプログラミングモデル • マシンを増やしただけスケール •Hadoop, MongoDB, CouchDB などが主な実装
  • 9. 入力 処理の流れ ↓ Map ↓ Reduce ↓ 出力
  • 10. やや厳密な 入力 処理の流れ ↓ Map ↓ Shuffle ↓ Reduce より厳密には ↓ もっと複雑らしいです 出力
  • 12. Shuffle •Map による Key/Value を • Key ごとにまとめて出力
  • 16. 入力 •to be or not to be
  • 17. Map •<"to", 1> •<"be", 1> •<"or", 1> •<"not", 1> •<"to", 1> •<"be", 1>
  • 18. Shuffle •<"be", [1, 1]> •<"not", [1]> •<"or", [1]> •<"to", [1, 1]>
  • 19. Reduce • <"be", 2> • <"not", 1> • <"or", 1> • <"to", 2>
  • 20. MapReduce の利点 •Map も Reduce も並列化 すればスケールする •関数型っぽい考え方が活きる ※ただし, Hadoop や MongoDB の MapReduce の Map と Reduce は  関数型言語のそれとはやや異なる (参照透過でなかったり) • パターンとして共有しやすい ※手続き型のバッチ処理と比較して
  • 21. MongoDB について • 通常は MapReduce を 並列に実行することができない • それでも MapReduce は便利 •何故か?
  • 23. MySQL でも MapReduce したい!!!
  • 25. MyMR https://github.com/yuya-takeyama/mymr •MySQL を入出力とする • PHP で Map/Reduce を書く • コマンドラインで実行
  • 26. MyMR による処理の流れ •テーブルからレコードを読む •1 行 1 行に Map (PHP) を適用して 中間テーブルへ •MySQL による Shuffle •その結果に Reduce (PHP) を適用して 出力テーブルへ
  • 27. に よ る yM R M 文章中の 単語の数を数える例 (word count)
  • 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. 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. 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. 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. 入力 •to be or not to be
  • 33. Map function ($record, $emitter) {     $words = preg_split('/s+/u', $record['text']);     foreach ($words as $word) {         $emitter->emit($word, 1);     } }
  • 34. Map レコードを 連想配列として受け取る function ($record, $emitter) {     $words = preg_split('/s+/u', $record['text']);     foreach ($words as $word) {         $emitter->emit($word, 1);     } }
  • 35. Map function ($record, $emitter) {     $words = preg_split('/s+/u', $record['text']);     foreach ($words as $word) {         $emitter->emit($word, 1);     } } text カラム内の 文字列をスペースで分割
  • 36. Map function ($record, $emitter) {     $words = preg_split('/s+/u', $record['text']);     foreach ($words as $word) {         $emitter->emit($word, 1);     } } Key/Value のペアとして 中間テーブルに INSERT
  • 37. Reduce function ($key, $values) {     $sum = 0;     foreach ($values as $count) {         $sum += $count;     }     return array('count' => $sum); }
  • 38. Reduce Key Value の配列 function ($key, $values) {     $sum = 0;     foreach ($values as $count) {         $sum += $count;     }     return array('count' => $sum); }
  • 39. Reduce Value を全て足す function ($key, $values) {     $sum = 0;     foreach ($values as $count) {         $sum += $count;     }     return array('count' => $sum); }
  • 40. Reduce function ($key, $values) {     $sum = 0;     foreach ($values as $count) {         $sum += $count;     }     return array('count' => $sum); } 返り値の連想配列を レコードとして INSERT
  • 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. +----+--------------------+ 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. +----+---------+-------+ | 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. +---------+--------+ | 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. +---------+--------+ | 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. モチベーション • プログラミングモデルとしての MapReduce を使いたい • MySQL を入出力にしたい •LL でサクッとやりたい
  • 47. モチベーション • プログラミングモデルとしての MapReduce を使いたい • MySQL を入出力にしたい •LL でサクッとやりたい PHP である必要はあまり無い
  • 48. 今後の目標 •非同期 INSERT による並列化 • Hadoop へのシームレスな 移行方法の提供
  • 49. まとめ • ビッグデータは無くとも MapReduce は有効 • MySQL でできたら便利なはず •PHP で書けたら楽しいはず
  • 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