2014年3月24日月曜日

ムック「データベース徹底攻略」 - MySQL/Redis/MongoDB/Redshift

最近発売された技術評論社のムック「データベース徹底攻略」に寄稿しました。

この本は、データベースのための本ということで、データベース設計、SQL、MySQL、Redis、MongoDB、Redshiftという代表的な要素技術についてのまとめとなっています。各プロダクト(MySQL、Redis、MongoDB、Redshift)については、現場で実際に本格的に使われている方々による記事なので大いに参考になると思います。

私は冒頭のまとめ記事を寄稿しました。詳細はぜひお手に取って読んでくださればと思います。ここでも自分が各技術を現時点でどのようにとらえているか、本ではいささか書きづらい内容について、最近流行りの言葉でもある「技術的負債」という観点も踏まえて書いておこうと思います。

・MySQL (RDBMS)
 私はMySQLの中の人でもありましたし、これまで至るところで話してきたので省略します。Facebookでの使い方に興味のある方は、Percona Live等で私をつかまえてくださればと思います。

・Redis (NoSQL)
 従来型RDBMSで扱いづらいデータ構造であるSortedSetsやListが使えるのが魅力のデータベースです。このためだけにソーシャルゲームのリアルタイム・ランキングや、動画の最新100件とかいった用途に採用しているケースもあります。正となるデータをRDBMSに、キャッシュ的に使うデータ(壊れてもRDBMSから復元可能なデータ)をRedisで、というパターンが多いです。耐障害性に難がありますが、キャッシュとして使う限りは許容範囲内だと思います。

・MongoDB (NoSQL)
 データベース設計ができない/できなかった/する時間が取れない、といった人たちや、Shardingのためのロジックを書くのがめんどくさい、といった人たちを中心に好まれるデータベースです。Facebookでも、子会社の中にMongoDBを使っているところがあります。
 MongoDBを使うか、RDBMSを使うかという議論は、よく「先に楽をして後で苦労するか、先に苦労して後で楽をするか」という表現にたとえられます。「技術的負債」を語る上で良いモデルケースと言えるでしょう。
 稼働までなら、MongoDBの方が、正規化が必須なRDBMSより楽です。その一方で、設計を放棄したツケは、後々になってデータ整合性問題、(重複値の多発による)データ量増加、それによるコスト増といった様々な負債となって現れます。裏の実装はMyISAMと大して変わらないので、データ量がメモリに乗らないくらいの規模になってくると、InnoDBよりも急激なペースで参照・更新性能とも悪化します。典型的な「技術的負債」のパターンと言えるのではないでしょうか。コスト増のことを「技術的負債」と言うのか? という意見もあると思いますが、そのコストの代償として間接的に給与が削減されたり、良いエンジニアを取りづらかったりといった不利益を受ける可能性がありますし、そのコストを減らすためには後々技術的な取り組みが必要になることから、「技術的負債」と言って良いのではないかと思います。ここではこれらの技術的・時間的・金銭的な不利益をまとめて「技術的負債」と呼ぶことにします。

 私が考えるMongoDBの魅力は、多くの場合に、こうした技術的負債を返済しなくて済むということです。負債が顕在化するのは、そのサービスが大きく成長した場合のみです。一般的なサービスの成功確率の低さを考えると、たいていのケースでは負債は返さなくて済みます。これは非常に魅力的なポイントです。競争に勝つためには、早期にサービスを出すことはとても大切で、様々な課題を先送りできるMongoDBがスタートアップを中心に好まれるのはある意味当然とも言えます。そもそも妥当な設計には正規化を中心としたデータベース基礎理論の理解が必要で、それに詳しい人をスタートアップで確保することは多くの場合難しいという事情も無視できません。サービスがうまくいったら、それなりにお金もあるはずなので、データベース設計に強い人を雇用することも難しくなくなってくるでしょう。

 ちなみに、元MySQL社の営業チームのメンバーの中にはMongoDB社に転職した人も何人かいます。上述のように導入時の優位性があるので、MongoDBの営業は「RDBMSよりも速くサービスを作り稼働させることができる」「シャーディングやフェイルオーバーなどの作り込みがいらないので実装コストが低い」などといった売り込みができます。営業は売ったもの勝ちなので、後々技術的負債がどうなるかを考えてくれたりはしません。それどころか、知り合いの賢いMongoDBの営業は、負債の顕在化によって後でサーバ台数がたくさん必要になったり、自動シャーディングやフェイルオーバーが期待通りに動かないことで、お客さんが困ってサポートをたくさん買ってくれるということまで見据えていたりします。怖いですね。
 なお、営業トークの1つである「RDBMSはスキーマ変更が大変」というのは、今の時代それほど重要では無いということを補足しておきます。MySQL5.6(InnoDB)ではオンラインDDLができますし、それ以前のバージョンでも無停止での変更手段はいくらでもあります。どちらかというと自動シャーディングや自動フェイルオーバーの方がセールストークとしては強力でしょう。

 一方でMongoDBを使う側としては、万一サービスがヒットした場合に必ず顕在化するであろう技術的負債について、どう取り組むかは考えておいた方が良いでしょう。現実解としては実績のある他RDBMSへの移行ですが、止めたときにユーザに直接影響が出る用途で使うことが多いでしょうから、移行するのはなかなか大変です。数少ない大規模リニューアル時やメンテナンス時などのタイミングで移すことになるでしょう。
 北米では、「規模が大きくなりすぎたMongoDBベースのWebサイトを、他のRDBMSに移行する」という案件も実際に存在するのですが、MongoDBを最初に導入した人はその時点では退職していたりします。MongoDB社、導入を進めた人、移植先のRDBMSベンダー、移植を進める人たち全員に仕事があるという、経済(GDP)に優しいデータベースとも言えるでしょうか?
 RDBMSとMongoDBのどちらが良いかについて一言でまとめるなら、「サービスが失敗したらMongoDBの勝ち、成功したらRDBMSの勝ち」というのが私の考えです。


・Redshift (ビッグデータ)
 PostgreSQLベースのDWH運用サービスで、AWS上で使うことができます。列指向、圧縮、複数ノード並列処理などひととおりの重要機構を備えています。Facebookでも、子会社の中にRedshiftを使っているところがあります。
 Redshiftは、特にコストパフォーマンスの観点で非常に優れています。2TBあたり年間数十万円で使えるという低価格は、1つのイノベーションと言えると思います。登場し始めた頃は、1週間で100社のペースで顧客が増えていたそうで、これを使うためだけにAWSに移行したという話も聞いたことがあります。機能の追加も良いペースで行われています。HDDベースとSSDベースがあり、価格と性能のトレードオフを踏まえた上で選べば良いでしょう。

 ビッグデータを扱う環境では、技術的負債という観点において、上に書いたMongoDBとは状況が異なります。すでにたくさんデータがあるということは、サービスとしてはそこそこ当たっている状況のはずです(そもそもデータが数10GBとかしか無ければ、RDBMSで十分です)。この先サービスが収束して終了する可能性はほぼ無いと考えられます。多くのスタートアップがMongoDBを使う背景にある「サービスが早期終了すれば負債は残らない」という予測は、DWHを必要とするほどの環境になると期待できません。負債は必ず顕在化します。必ず顕在化するのであれば、そうならないように事前に手を打っておくことはとても重要です。
 正規化などを含めた様々なことを先送りして、Redshiftのかわりに他の手段を採用するとした場合、その代償について慎重に吟味する必要があります。特に容量単価をはじめとしたコスト面で割高な場合は、データ量が増えれば増えるほどコスト差が広がるのでより深刻です。サービスが存続する限り、拡大するコスト差を負担し続けなければならず、それを改善するためには、データの削除や保持期間の縮小、後からRedshiftに移行する、といった手間をかけなければいけないからです。これも「技術的負債」の典型的なケースと言えます。
 このような点から、私はビッグデータに関しては、後で苦労するくらいなら先に苦労した方が良いという、技術的負債を先送りしないアプローチを取りたいと考えます。現時点での私の大まかな感覚では、これから3年間使うとして、そのトータルコストが4TB(圧縮後)あたり600万円~900万円(3年の累計)、10TBあたり1000万円~1500万円のレンジを超えてくるようなら、すでに技術的負債と言える(=より低コストな手段を模索すべき)と思います。このレンジは時間の経過とともにもっと下がるのは確実です。
 AWSでビッグデータを扱うのであれば「Redshiftを使いこなせれば勝ち、そうでなければ負け」というのが私の考えです。幸いDWH環境の場合、メインのWebサービスに比べて可用性や安定性に対する要求が低く(利用者が社員など一部に限定されるので)、止めて移行することは現実的に可能です。だからこそ過剰投資を防ぐ余地があります。すでに高コストな選択肢を選んでしまったとしても、手遅れではありません。稼働後もいかに(Redshiftなどで)トータルコストを下げる(技術的負債を減らす)かを模索していくと良いのではないかと思います。こうした低コスト化の推進の効果を、エンジニアたちの所得アップに還元してくれる会社がたくさん出てくると良いなと思います。

 Redshiftを見ていると、商用RDBMSの世界を徐々にMySQLが侵食していった頃のことを思い出します。当然ながら商用DWHベンダーにとって、低価格なRedshiftの登場は面白く無いわけです。「MySQLはXXがダメだ、だからYY(商用RDBMSの名前)を使いましょう」とアピールしていくことが、(より高い)商用RDBMSベンダーや、そのパートナー企業の人たちの仕事でした。ユーザにとってベストなのかどうかは関係ありません。ベンダーにとってベストなことをするのがベンダーの論理です。MySQLは最もコスト競争力が高いRDBMSだったため、歴史的にずっとこの攻撃を受ける側でした。同じように、商用DWHベンダーは、例えRedshiftで実現可能なことであっても、さも実現できないかのようにアピールし、自社の(より高い)DWH製品を勧めていくという戦略を取ります。ユーザーのためになっていないですが、それが商用DWHベンダーの人たちの仕事なのです。読者の皆さんには、こうしたネガティブマーケティングに惑わされないようにしてほしいと思います。

13 件のコメント:

匿名 さんのコメント...

http://myrocks.io/ Meta Open Source https://opensource.fb.com/ Developer(s) Meta Platforms, Inc.

匿名 さんのコメント...

Website Design https://www.yoshinorim.com/

匿名 さんのコメント...

Website Design https://www.yoshinorim.net/

匿名 さんのコメント...

Meta Platforms, Inc.

匿名 さんのコメント...

http://myrocks.io/ Meta Open Source https://opensource.fb.com/ Meta Platforms, Inc.

匿名 さんのコメント...

Website Design https://www.yoshinori.matsunobu.com/ https://php.net/ https://python.org/ https://perl.com/

匿名 さんのコメント...

Website Design https://www.matsunobus.com/ https://php.net/ https://python.org/ https://perl.com/

匿名 さんのコメント...

Website Design https://www.matsunobu.com/ https://php.net/ https://python.org/ https://perl.com/

匿名 さんのコメント...

http://myrocks.io/ Developer(s) Meta Platforms, Inc.

匿名 さんのコメント...

Website Design https://www.matsunobus.com/contact-us https://www.php.net/ https://www.python.org/ https://www.perl.org/

匿名 さんのコメント...

[email protected]

匿名 さんのコメント...

Website https://www.matsunobus.com/

匿名 さんのコメント...


Yoshinori Matsunobu - Database Engineer @ Meta, Inc.

コメントを投稿

'},ClipboardSwf:null,Version:'1.5.1'}};dp.SyntaxHighlighter=dp.sh;dp.sh.Toolbar.Commands={ExpandSource:{label:'+ expand source',check:function(highlighter){return highlighter.collapse;},func:function(sender,highlighter) {sender.parentNode.removeChild(sender);highlighter.div.className=highlighter.div.className.replace('collapsed','');}},ViewSource:{label:'view plain',func:function(sender,highlighter) {var code=dp.sh.Utils.FixForBlogger(highlighter.originalCode).replace(/'+code+'');wnd.document.close();}},CopyToClipboard:{label:'copy to clipboard',check:function(){return window.clipboardData!=null||dp.sh.ClipboardSwf!=null;},func:function(sender,highlighter) {var code=dp.sh.Utils.FixForBlogger(highlighter.originalCode).replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');if(window.clipboardData) {window.clipboardData.setData('text',code);} else if(dp.sh.ClipboardSwf!=null) {var flashcopier=highlighter.flashCopier;if(flashcopier==null) {flashcopier=document.createElement('div');highlighter.flashCopier=flashcopier;highlighter.div.appendChild(flashcopier);} flashcopier.innerHTML='';} alert('The code is in your clipboard now');}},PrintSource:{label:'print',func:function(sender,highlighter) {var iframe=document.createElement('IFRAME');var doc=null;iframe.style.cssText='position:absolute;width:0px;height:0px;left:-500px;top:-500px;';document.body.appendChild(iframe);doc=iframe.contentWindow.document;dp.sh.Utils.CopyStyles(doc,window.document);doc.write('

'+highlighter.div.innerHTML+'

');doc.close();iframe.contentWindow.focus();iframe.contentWindow.print();alert('Printing...');document.body.removeChild(iframe);}},About:{label:'?',func:function(highlighter) {var wnd=window.open('','_blank','dialog,width=300,height=150,scrollbars=0');var doc=wnd.document;dp.sh.Utils.CopyStyles(doc,window.document);doc.write(dp.sh.Strings.AboutDialog.replace('{V}',dp.sh.Version));doc.close();wnd.focus();}}};dp.sh.Toolbar.Create=function(highlighter) {var div=document.createElement('DIV');div.className='tools';for(var name in dp.sh.Toolbar.Commands) {var cmd=dp.sh.Toolbar.Commands[name];if(cmd.check!=null&&!cmd.check(highlighter)) continue;div.innerHTML+=''+cmd.label+'';} return div;} dp.sh.Toolbar.Command=function(name,sender) {var n=sender;while(n!=null&&n.className.indexOf('dp-highlighter')==-1) n=n.parentNode;if(n!=null) dp.sh.Toolbar.Commands[name].func(sender,n.highlighter);} dp.sh.Utils.CopyStyles=function(destDoc,sourceDoc) {var links=sourceDoc.getElementsByTagName('link');for(var i=0;i');} dp.sh.Utils.FixForBlogger=function(str) {return(dp.sh.isBloggerMode==true)?str.replace(/
|<br\s*\/?>/gi,'\n'):str;} dp.sh.RegexLib={MultiLineCComments:new RegExp('/\\*[\\s\\S]*?\\*/','gm'),SingleLineCComments:new RegExp('//.*$','gm'),SingleLinePerlComments:new RegExp('#.*$','gm'),DoubleQuotedString:new RegExp('"(?:\\.|(\\\\\\")|[^\\""\\n])*"','g'),SingleQuotedString:new RegExp("'(?:\\.|(\\\\\\')|[^\\''\\n])*'",'g')};dp.sh.Match=function(value,index,css) {this.value=value;this.index=index;this.length=value.length;this.css=css;} dp.sh.Highlighter=function() {this.noGutter=false;this.addControls=true;this.collapse=false;this.tabsToSpaces=true;this.wrapColumn=80;this.showColumns=true;} dp.sh.Highlighter.SortCallback=function(m1,m2) {if(m1.indexm2.index) return 1;else {if(m1.lengthm2.length) return 1;} return 0;} dp.sh.Highlighter.prototype.CreateElement=function(name) {var result=document.createElement(name);result.highlighter=this;return result;} dp.sh.Highlighter.prototype.GetMatches=function(regex,css) {var index=0;var match=null;while((match=regex.exec(this.code))!=null) this.matches[this.matches.length]=new dp.sh.Match(match[0],match.index,css);} dp.sh.Highlighter.prototype.AddBit=function(str,css) {if(str==null||str.length==0) return;var span=this.CreateElement('SPAN');str=str.replace(/ /g,' ');str=str.replace(/');if(css!=null) {if((/br/gi).test(str)) {var lines=str.split(' 
');for(var i=0;ic.index)&&(match.index/gi,'\n');var lines=html.split('\n');if(this.addControls==true) this.bar.appendChild(dp.sh.Toolbar.Create(this));if(this.showColumns) {var div=this.CreateElement('div');var columns=this.CreateElement('div');var showEvery=10;var i=1;while(i<=150) {if(i%showEvery==0) {div.innerHTML+=i;i+=(i+'').length;} else {div.innerHTML+='·';i++;}} columns.className='columns';columns.appendChild(div);this.bar.appendChild(columns);} for(var i=0,lineIndex=this.firstLine;i0;i++) {if(Trim(lines[i]).length==0) continue;var matches=regex.exec(lines[i]);if(matches!=null&&matches.length>0) min=Math.min(matches[0].length,min);} if(min>0) for(var i=0;i

自己紹介

松信 嘉範(MATSUNOBU Yoshinori)

2001年にソニー株式会社に入社して以来IT業界で過ごしています。Oracleを2001年から、MySQLを2004年から使っており、2006年9月にMySQL株式会社に転職しました。このオープンソースRDBMSの道に足を大きく踏み入れる決断をした結果、会社の滅亡を2度経験。キャリアの建て直しに尽力する日々です。問い合わせ先はYoshinori.Matsunobu at gmail.comまで。

執筆した書籍

セミナー資料等

 こちらにまとめて公開しています

フォロワー

Twitter Updates

    follow me on Twitter

    ブログ アーカイブ