第2回 MongoDB JP 勉強会 in Tokyoに参加してきました
おまけに久しぶりに発表までしてきました。
ざっくり内容を書いておくと
- mongodbは固定フォーマットではないデータをとりあえず投入して構造化できるので、解析初期に非常に便利
- mongoimportは標準入力でいけるので、hadoop/hiveのstreamingと相性いい
- mongoimportは標準入力でいけるので次のようにフィルタをかませられる
$ cat access.log | perl ./filter.pl | mongoimport -d mydb -c mycollection --fields ip,timestamp,method,host,uri,useragent
- mongodbのmapreduceはkey/valueを縦横無尽に検索したり集計したりできるので、解析初期に便利
- mongodbのmapreduceはhadoopのそれと比べると、sort&shuffleが隠されていて無い、(おそらく)それを補うようにfinalizeが付いてる
- ただfinalizeは最終的なmapreduce成果物を全然入れ替えるほどの力がある
var out = 'hoge', map = function(){ emit(ua, 1); }, reduce = function(k, vs){ return Array.sum(vs); }, finalize = function(k, out){ var career = k.match(/(KDDI)|(DoCoMo)|(SoftBank)/); return {cnt: out, sumtime: new Date(), career: career[1]}; }; db.col.mapReduce(map, reduce, {fianlize: finalize, out: out}); db.hoge.find(); // もし、finalizeがなければしたみたいな{_id: UA, value: 回数}みたいなのが返ってくる {_id: "ua1", value: 10} {_id: "ua2", value: 20} {_id: "ua3", value: 30} {_id: "ua4", value: 40} // でも、finalizeがあるので、したみたいな全然違うオブジェクトを作ることができる {_id: "ua1", value: {cnt: 10, sumtime: ISODate(XXX), career: "KDDI"}} {_id: "ua2", value: {cnt: 20, sumtime: ISODate(XXX), career: "DoCoMo"}} {_id: "ua3", value: {cnt: 30, sumtime: ISODate(XXX), career: "KDDI"}} {_id: "ua4", value: {cnt: 40, sumtime: ISODate(XXX), career: "SoftBank"}}
- ただ、世の中にはmapreduceの実例がほとんど無い(googlabilityが低い)
- mapReduceで重要なパラメタはフィルタリングの意味のquery(64bitでも、すぐにout of memory的なこというから)と、out.merge(出力先をmergeすることはaccess.log解析ではJKといっても過言ではない)
- mongodbは特性上、フォーマットはでたらめでいいけどtimestampだけは最低合わせておく(ISODateでもNumberでも)
- PV/UU/Session集計のサンプル書いておいた
- PV
// 1時間ごとのPV var col = db.logs, out = db.logs.hour, begin = new Date(), map = function(){ var dt = new Date(this.timestamp), os = OSDetector(this.ua), browser = BrowserDetector(this.ua); emit({host: this.host, timestamp: new Date(dt.getFullYear(), dt.getMonth(), dt.getDay(), dt.getHours(), 0, 0)}, {cnt: 1, os: os, browser: browser); }, reduce = function(k, vs){ var out = {cnt: 0, os: {}, browser: {}}; vs.forEach(function(v){ out.cnt += v; if(out.os.hasOwnProperty(v.os)){ out.os[v.os] += 1; }else{ out.os[v.os] = 1; } if(out.browser.hasOwnProperty(v.browser)){ out.browser[v.browser] += 1; }else{ out.browser[v.browser] = 1; } }); return out; }, finalize = function(k, out){ return out; }; col.mapReduce(map, reduce, {finalize: finalize, out: {merge: out}}); print('create col '+out+' begin '+begin+', end '+new Date());
-
- UU
var o = 'logs.hour.uu.tmp', col = db.logs, map = function(){ var dt = new Date(this.timestamp); emit({timestamp: new Date(dt.getFullYear(),dt.getMonth(),dt.getDay(),dt.getHours(), 0, 0), user: this.session, host: this.host}, 1); }, reduce = function(k, vs){ var sum = 0; vs.forEach(function(v){ sum += v; }); return sum; }; col.mapReduce(map, reduce, {out:out}); var o = 'logs.hour.uu', col = db.logs.hour.uu.tmp, map = function(){ emit({timestamp: this._id.timestamp, host: this._id.host}, {pv: this.value, uu: 1); }, reduce = function(k, vs){ var pv = 0, uu = 0; vs.forEach(function(v){ pv += v.pv; uu += v.uu; }); return {pv: pv, uu: uu}; };
-
- セッション集計 (counting session)
var o = 'logs.hour.session, map = function(){ var dt = new Date(this.timestamp); if(!this.ref.indexOf(this.host)){ // こういうところでちょっとした工夫が出来るところがmongodb mapReduceの面白いところ emit({timestamp: new Date(dt.getFullYear(), dt.getMonth(), dt.getDay(), dt.getHours(), 0, 0), user: this.session, host: this.host}, 1); } }, reduce = function(k, vs){ var sum = 0; vs.forEach(function(v){ sum += v; }); return sum; };
- ごめんなさい。スライド後で見返したら、chrome以外うまく見られないかも >
mongodb benchmark (import/ find/ mapreduce) N=5
- VM mini
process | No Sharding x No Striping | No Sharding x Striping | Sharding x No Striping | Sharding x Striping |
---|---|---|---|---|
mongoimport | 9m9.201s | 8m40.438s | 10m30.101s | 11m30.042s |
find | 38.37796 | 42.29296 | 13.61808 | 14.99836 |
mapreduce | 226.64 | 229.46 | 107.39 | 106.85 |
- VM large16
process | No Sharding x No Striping | No Sharding x Striping | Sharding x No Striping | Sharding x Striping |
---|---|---|---|---|
mongoimport | 4m19.671s | 1m44.757s | 4m23.050s | 3m13.803s |
find | 1.04364 | 1.0296 | 1.12412 | 1.13192 |
mapreduce | 52.53 | 52.10 | 26.08 | 26.08 |