専門職及び管理職両者の立場から見たITベンチャーにおける技術 -財務会計をからめて-
2017/5/13
euler.bonjour@gmail.com / https://github.com/khj1977
金輝俊 / Hwi Jun KIM
注:本文章は5/13に作成した文章をタイトル、セクション名のみについて、一部改変してあ る。
1. 億単位のレコードの困難性、MySQLの限界、ハードウェアコストと財務会計
2008年当時、1億レコードをMySQL(MyISAMがストレージエンジン)にinsertするだけで24時 間かかったと記憶している。24時間でのInsert数が1億レコードを超えるとMyISAMがぶっ壊 れた事があったと記憶している。
注:DBへの書き込み側は別のエンジニアが担当していた
当時の会社では、全体では解析用DBにストレージエンジンとしてMyISAMを使用していた。個人 的には別の理由でInnoDBを使用していた。当時の解析対象をMySQL(InnoDB)に突っ込むと、 DB数億レコードで数GB - 10数GBの容量になった。
もう少しMySQL(MyISAM)の限界について述べる。バルクインサートあるいはパラメータの チューニングなどをしても、24時間で1億インサートしかできない事が分かった。当時、24時 間で2億インサート以上する必要があった。MySQL用のシャーディングのためのソフトウェア開 発の検討を会社で行った。同時にRAIDで組んだHDDがぶっ壊れるなどの事象が起こった。ハー ドウェアコストと増え続けるデータとDBレコード数。HDDを無限に増やす事はできない。そし て、財務会計上のハードウェアコストの限界を考える必要性が出てきた。
したがって、いかにローコストでかつ、理想的な実装もしくは設計方針でないが、結果を出す ためのアーキテクチャ及びアルゴリズムの開発の方向性にさらに進む事になった。そして、SQL レベルでは、SQLのチューニングにアルゴリズム開発中に時間をかけることになった。
例えば、あまり考えてないSQLをそのくらいの規模のDBに投げるとクエリが数十分、へたする とかなりの長時間返ってこなかった。インデックスがどうとかそういう問題ではない。
インデクスについて述べる。MySQLではnested loop joinがjoinのアルゴリズムとして使 用されていると思う。従って、インデックスを張ってもO(nlog n)の計算量が必要なはず。な ので、億単位でDBになると場合によってはクエリの結果が数十秒あるいは数十分返ってこない 場合があった。
他の例を挙げると2012年のweb系での話だが、複数テーブルがあり、一つのテーブルに300万 レコードがあった。その複数テーブルをリアルタイム処理系でjoinさせるとほぼリアルタイム 処理系の要求を満足した。別の例では1000万レコードであってもクエリが複雑になると30秒以 上結果がかえってこない事があった。
したがって、ある程度の規模のDBではSQLの書き方によってはクエリが返ってくる速度が数秒 とかそういう単位でなく、かなり遅いというのはある程度正しいと思う。
億単位のレコード数のDBでJOINをすると遅いことは分かっていたので、テーブルはほとんどが 非正規化されていた。その会社の当初の解析用DBは普通に正規化されていたが、途中から、DB 構造をあらため、非正規化していた。
非正規化の結果、必要ならクエリの結果をプログラム側でjoinさせるなどしていた。当時、正 確に計測したわけではないが、DBでjoinさせるより、そちらの方が高速だという結論に達して いた。
注:DB自体の非正規化は他のエンジニアが主導して進めていた。 注:joinの問題がなくなっても、GROUP BYやSORTの問題は残る。本質的には似たような問題 だと考える。
ストレージエンジンによるSQLのクエリ結果のパフォーマンスへの影響について述べる。 InnoDBではMVCCがロックの代わりに使われている。億単位のレコード数でInnoDBでSELECT をかけるとMVCCの実装上の限界により、レコード数比例でSELECTに時間がかかってしまった 可能性があった。MyISAMだとそういう可能性は低い。ただし、解析用DBを複数人で共有する か、あるいは複数の解析バッチを投げる時はInnoDBの方が有利な可能性が高かった。なぜな ら、MyISAMはSELECTでテーブルロックがかかり、並列アクセスが難しいと考えたからであ る。逆に、InnoDBはMVCCのため、SELECTではロックがかからないからそちらを上記前提条件 の元、採用した。
ただし、サーバーのメモリ容量及び、データ容量によってはデータがキャッシュされうる割合 が高くなる可能性があり、似たようなレコード数であっても、クエリの結果の返ってくる速度 は違う可能性が高い。なぜなら、システム毎に1レコード数あたりのデータ容量が違う場合が 多々あるからである。また、オプティマイザの働き方も違い、なんとも言えない所も出てく る。ただし、だいたいにおいて、上記のような特性を持っていたと考える。
総合すると、当時のハードウェア限界、財務会計上のコスト限界、時間及び、人的リソースの 限界を考えると、理想的な実装及び、設計方針ではないが、1. シャーディングと全てのデータ をDBに保存することをあきらめ、2. かつ、SQLのチューニングやその上に乗るアルゴリズムの 工夫でなんとかしようという風に進んでいったと記憶している。
当時はまだエントリーレベルのエンジニアであったが、あまりコストをかけず、アーキテク チャあるいはアルゴリズムで工夫し、経営サイドの要求を満たしつつ、アルゴリズム開発を進 む方向性が加速していった。
最近はアルゴリズム開発はしていないが、その考え方は残っており、いかに財務会計上の制 限、人的リソースの制限、時間の制限はあるが、エンジニアとしてやりたいこと、事業の方向 性を考慮して開発をしていた。そして、そこに面白さを感じていた。
2. 事業会社でのWebシステム、技術と業務部門と室長としての立場
2016年当時、スーツ販売のECの会社に所属。この会社には部門が複数存在した。例えば、生産 (配送、工場とのやりとり)、マーケティング、商品企画、店舗関連部門などがある。それぞ れすべて関連性があり、初期は特にある程度マンパワーで結びついていたが、徐々にシステム 化しようという傾向になっていった。
上記システムは一見するとwebシステムでありがちな管理画面を作っているだけに思われる。 UIなどの派手さがなく単なるCRUDシステムと思われがちなので、単にbootstrapで適当に作ればいいじゃん、と思われがち。
実際は画面の問題というより、社内あるいは社内と社外のプロセスの問題となる。例えば、1. ECでのお客様のオーダー。2. 社内での処理。3. 発注書作成など。工場へデータを渡す。一見 すると単純なようだが、上記のうち、特に2がおかしいとお客様への納期が遅れてしまうという 結果になる。直感的にもそうであるが、分析結果でもある程度CVRと納期の関係性はある程度正 の相関があるという結果が出ていた。
2は上記ではさらっと書いているがA2-3枚分のフローチャートで可視化されたプロセスが存在 し、かなり複雑であった。これを最適化し、システム化することによって、ECのお客様からみ れば、納期が縮み、利便性が高まり、会社側から見ると、CVR及び売り上げが上がる結果とな る。また、社内のオペレーション部門からみると、業務上の負荷が下がり、仕事が楽になると いう結論になる。
実際はシステム化する前に、エクセルでプロトタイピングすることになった。開発側からみる と、プログラムを組まないというのは不満に思うかもしれないが、マネージメントサイドから みると、最小限の投入コストである程度回る業務を作れてしまうので、それでいいのではない かという事になる。
しかしながら、エンジニアサイドからみると、それだとデータ不整合や関連する会計上の問題 が出てくるので、なるべくならさけたい。しかしながら、初期のプロトタイピングおよび、リ ソース、すなわち時間の制限を考えると、データ不整合や会計上の問題に目をつぶっても、こ ちらを取るという結論になると思う。
個人的にはプログラムを組むのは好きだが、あくまでも会社あるいは関係者のためにコードを 書いているので、マネージメントサイド、業務部門、エンジニアサイド、それぞれのバランス を取り、上記のような考えを持つ。
上記ではさらっと書いているが、システム開発部、オペレーション部、グロースハック室、経 営企画部、それぞれの考えがあり、サクサクと話が進むものではなく、もろもろ調整が必要 だったりし、そこが面白くも、難しいところであった。
3. 2004年以来のWeb周りの新規技術について -Comet, WebSocket, NoSQL, MapReduce-
通常のWebシステムはstrutsやrailsに代表されるようにfront controller patternの MVCフレームワークを用いて実装されるが、アーキテクチャ的にみるとJS + WebSocket + APIサーバーによるシステムはobserver patternのように実装する事ができる可能性があ る。2010年以降のMeteorやreactive programmingなどはこの流れだと思うが、これは本 当に新しいのであろうか?Web システムでも2006年くらいにCometの話題が出始めたと思う。 どういう事かと言うと、例えば、ApacheやXMLHttpをうまく使えばWebSocketを使わなくて もobserver patternっぽいことができた。歴史をさらに遡ると、observer patternベー スのアプリケーション構築はすでにSmalltalk-83が始まりだったのではないかと記憶してい る。PCでもMacやNeXTStep、続くMacOSXに引き継がれていたはずだと思う。もっと顕著な例 だと、サーバーと組み合わせたシステムでもおそらくVB + サーバーサイドプログラムのクラ サバ構成は上記JS + WebSocket + APIサーバーによるobserver pattern的なシステムと対して変わりないはず。過去のクラサバ的なシステムと現代のwebsocketベースで実装可能だ と思われるobserver pattern的なシステムの相違点はライセンスがGPLなどのため、エンジ ニアサイドから見るとソースが読め、マネージメントサイドから見ると、場合によってはシス テム構築の費用を抑えられる点にあると思う。
このような例は他にも見られると思う。2010年くらいにNoSQLが流行ったと記憶しているが、 そのときの主流のNoSQL DBは大抵が主要データ構造が昔とあまり変わってないとちょっと調べ た限りでは記憶している。例えば、Berkey DBはハッシュベースのNoSQLであり、少なくとも 1990年代後半には存在していた。Redisはインデックスとしてhash、mongoはインデックスと してbtreeの変種を用いていたと記憶している。教科書的なベーシックな実装でなく、色々工 夫しているのかもしれないが、インデックスのベースとなるデータ構造は変化せず、よって、 インデックスを使用したデータへのアクセススピードはオーダーベースではドラスティックな 変化はしていないと思われる。もちろん、細かい実装あるい設計方針、例えば、データ保存方 法、など細かい所は変わっていて、過去よりは進化しているだろうが、この例でも昔とは本質 的には変わってないのではないだろうか、という印象。
ここ20年くらいで新しいと思ったのはMapReduceと周りの並列分散処理システムくらいだと思 う。Googleを支える技術かなんかで読んだと記憶している。全体的にこの並列分散処理システ ムは一般的なOSの概念の一般化として見えたと記憶している。例えば、ロックか何かだったと 思うが、これは一般的なUNIXシステムのセマフォの概念を一般化して、並列分散処理システム としてうまくまとまっていて、これは新しいと思った。他のMapReduce周りのエコシステムも 同様だと思った。
総合すると、ここ20年で一番興味があったのはMapReduceと周りのエコシステムくらいだと思 う。ミドルウェアに顕著だが、他のOSSあるいは技術は、昔より設計方針、あるいはパフォーマ ンスなどが向上しているものが出ていると思うが、本質的に新しいものは出てきてないという 印象。
ただし、この考え方は本質的に新しい技術とは何か?という立脚点に立っているので、実務上の視点から見るとまた別の意見になると思う。個人的にはわりと前者よりになるが、仕事をする上では多少、後者の視点も取り入れている。