Contenu connexe Plus de Yuya Takeyama (13) PHP と MySQL で 1 カチャカチャカチャ...ッターン! MapReduce (@ニコニコ超会議)1. PHP と MySQL で
1-Click
MapReduce
(@ニコニコ超会議)
@yuya_takeyama
4. PHP と MySQL で
1-Click
1カチャカチャカチャ...ッターン!
MapReduce
(@ニコニコ超会議)
@yuya_takeyama
5. N番煎じでお送りします
• 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
• PHP と MySQL でカジュアルに MapReduce する
(スライド・Long Version)
http://www.slideshare.net/taketyan/php-mysql-mapreduce
• PHP と MySQL でカジュアルに MapReduce する
(スライド・Short Version)
http://www.slideshare.net/taketyan/php-mysql-
mapreduce-short-version
8. 入力
処理の流れ ↓
Map
↓
Shuffle
↓
Reduce
↓
出力
21. それ
MySQL で
も1
カチ
ャカ
MapReduce チャ
...っ
ター
ン!
で
したい!!!
24. モチベーション
•
もち プログラミングモデルとしての
ろん
1カ
MapReduce を使いたい
チャ
カチ
ャ...
• GROUP BY では難しい集計ッタ
ーン
!で
• MySQL を入出力にしたい
PHP である必要はあまり無い
• LL でサクッとやりたい
26. MyMR
https://github.com/yuya-takeyama/mymr
•MySQL を入出力とする
• PHP で Map/Reduce を書く
• カチャカチャ...ッターン!で実行
30. に よ る
yM R
M
文章中の
単語の数を数える例
(word count)
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);
});
return $builder;
32. 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;
33. 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;
34. 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;
37. Map レコードを
連想配列として受け取る
function ($record, $emitter) {
$words = preg_split('/s+/u',
$record['text']);
foreach ($words as $word) {
$emitter->emit($word, 1);
}
}
38. Map
function ($record, $emitter) {
$words = preg_split('/s+/u',
$record['text']);
foreach ($words as $word) {
$emitter->emit($word, 1);
}
} text カラム内の
文字列をスペースで分割
39. Map
function ($record, $emitter) {
$words = preg_split('/s+/u',
$record['text']);
foreach ($words as $word) {
$emitter->emit($word, 1);
}
}
Key/Value のペアとして
中間テーブルに INSERT
40. +----+--------------------+
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 |
+----+---------+-------+
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
value には JSON で入れるので | 1 |
| 5 | to
構造化データも使用可能 | 1 |
| 6 | be | 1 |
+----+---------+-------+
42. +----+---------+-------+
| 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. Reduce
Key Value の配列
function ($key, $values) {
$sum = 0;
foreach ($values as $count) {
$sum += $count;
}
return array('count' => $sum);
}
45. Reduce
Value を全て足す
function ($key, $values) {
$sum = 0;
foreach ($values as $count) {
$sum += $count;
}
return array('count' => $sum);
}
47. +---------+--------+
| 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 |
+----+---------+-------+
48. +---------+--------+
| 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 |
+----+---------+-------+
51. 今後の野望
もち
• ろん エンジンとかで
V8 1
カチ
ャカ
• チャ
ストレージエンジン API を
...ッ
ター
• カジュアルに叩いて ン!
で
•MapReduce したい