なぜRDBからCSV + COBOLに変更する事でコスト削減と高速化を同時に実現出来たかの考察
- そもそも既存はどんなロジック?
- RDBなんだからWhere句使ったら?
- なぜファイルにすると速くなるのか?
- 並列化と分散処理による高速化の可能性
- COBOL使う必要あったの? Javaとかじゃダメだったの?
- まとめ
TLを見てると以下の記事が少し話題になってました。
tech.nikkeibp.co.jp
tech.nikkeibp.co.jp
対象の記事は有料会員じゃないと見れないのだけど事例としては以下みたい。
リソース - ユーザー事例 - COBOL製品 ユーザー事例 : マイクロフォーカス
さて、この記事の驚きポイントは﹁1億レコードくらいのDB処理をRDBからCOBOL + CSVに変更してUnixサーバからWindowsサーバに変える事で性能を維持しつつコストを1/5くらいにした﹂という事でしょう。
﹁せっかく7割もあったSQLを全部COBOLに変えるとか時代に逆行しすぎ!﹂とか﹁RDBをファイルに変えるなんてとんでもない﹂とか思う人も多いんじゃないでしょうか。とりあえず私は思いましたw
しかし実際に高速化はありえるのか、その理由を分析していきましょう。
そもそも既存はどんなロジック?
中の人じゃ無いので分かりません! 分かりませんが、推測はできます。 1年分が約1億レコードに迫るデータ量で、それを1度に数年分扱う大規模システムである 毎月、会員保険会社から契約情報、保険金支払情報などのデータを収集、機構内でデータを処理した上で料率計算の基礎データ作成を行います 月次処理として過去情報から利率を求めるってことは本質的にオフラインバッチです。つまり、トランザクションの考慮は不要です。 もともとこれはメインフレームで稼働していました。〜中略〜 2003年にUNIX環境へ移植 COBOLシステムは日本IBM製のメインフレームで稼働しており、保守コストの高さも問題になっていた。 その内訳はSQLが7割、COBOLが2割、C言語が1割。SQLのユーザー定義関数を利用し.... 直接の移植はUnixからですが、ベースのビジネスロジックはメインフレームで作成されていた事が分かります。 SQLが7割もあるのでハッキリとは断言できませんが、メインフレームで作っているならベースのビジネスロジックはIMSのような階層型データベースやVSAMといったファイルベースの可能性があります。 その場合、RDBを使っていても単にキーでデータを取得する単なる箱になっている可能性は高いです。 というのもIMS/VSAMはSQLのような条件付きデータ取得ができません。そのため典型的なメインフレームでのDB操作は﹁全てのレコードを読み込んでプログラムで柔軟に条件判定を行う﹂という作りをしています。 疑似言語 + SQLで書くと以下のような処理はsql = "SELECT SUM(amount) FROM hoge WHERE flag == 3" result = db.exec(sql) puts resultメインフレーム的なアーキテクチャだと以下のように書く必要があります。
def isValid(record) record.flag == 3 end sum = 0 db.get('hoge').records.each{|record| if isValid(record) sum += record.amount end }全部データをPG側で舐めているのでフルスキャンと同等、いえネットワークコスト等も加味するとそれ以上の負荷がかかる事は容易に想像できるでしょう。 公開されてる情報からは想像の世界を出ませんが、メインフレーム時代から使ってるならこのような構造の可能性は高く、今回はその方向で考えます。
RDBなんだからWhere句使ったら?
さて、既存のビジネスロジックが前述した通り総ナメ処理だと仮定し、性能が足りないという状況。皆さんならどう改善しますか? ほとんどの人は﹁ちゃんとRDBに仕事をさせろ、WHERE句使え。最悪インデックスが無くてもそっちのが爆速﹂と考えるでしょう。 王道ですね。しかし、単純にそうはいかないケースが多々あります。 例ではisValid
はシンプルにレコードの中の特定カラムの値を比較するだけでした。
しかし、実際は遥かに複雑な条件判定ビジネスロジックが幾重にも使われてる可能性が高いです。別のテーブルの値と相関比較は当たり前に出てきます。そもそもそもそもDBの数字型や文字列型では無く、COBOLのデータ型のバイナリがそのままRAWとして突っ込まれている可能性すらあります。古いコードはデータ容量節約のためにboolean的なフラグとか使わずにビットをシフト演算で判定するとかあるあるですし。
こうなってくると単純にWHERE句に入れるのは難しい。
根本的なビジネスロジックを考え直すか、JOINやCASE文を駆使してSQLに無理やり判定処理を移植するしか無いです。そして、後者はフルスキャンになりがちですし性能が伸び悩むこともあるんじゃ無いかと。
ユーザ定義関数を色々使われてるし、7割もSQLがあるということは割と後者寄りの対応が元々はされていたのかもしれないです。
前者の根本対応が出来ればベストですがそれは基本設計からやり直しなので、移植や更改レベルのコストだと割に合わない可能性は高そうです。