フロントエンドを100000000倍速くした(゚∀゚)

フロントエンドを100倍速くした( ^ω^) を読んで私むかし100000000倍早くしたな、と思ったので思い出話を雑記です。

データベースマイグレーションの思い出

その昔データベースのマイグレーションのお仕事をしました。
Oracle製プログラムをDB2に対応させるのです。
そのプログラムはなんとも関数、プロシージャの巧みな使い手で数100はくだらない数のオブジェクトがありました。結果何が起こったのか。

10カラム、ストアド関数をSELECT実行

(サンプルです)

db2 => select
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0)
db2 (続き) => from dual
db2 (続き) =>
db2 (続き) => /

1                    2                    3                    4
    5                    6                    7                    8
        9                    10







SQL0437W  この複合照会のパフォーマンスが最適ではない可能性があります。理由コード

: "1"。  SQLSTATE=01602

     73.00000000          73.00000000          73.00000000          73.00000


000          73.00000000          73.00000000          73.00000000          73.0
0000000          73.00000000          73.00000000

選択された 1 レコード (1 警告メッセージ) が表示されました。

説明:
照会が複雑なために、使用できないリソースを要求しているか、または最
適化境界条件が見つかったために、ステートメントのパフォーマンスが次
善のパフォーマンスになる可能性があります。以下が理由コードのリスト
です。

sqlcode : +437
sqlstate : 01602

データベース構成ファイルのステートメント・ヒープ (stmtheap)の大きさを増やしてください。と言われた。

実行にかかる時間、およそ30分………
Oracleではもともと、3秒ほどで結果がかえっていたもの。

そのストアドの中身(サンプル)

stored.sql
CREATE FUNCTION OBJECT_PKG.GET_CONTENT (p_id DECIMAL(10,0), 
                                        p_date TIMESTAMP, 
                                        p_sts DECIMAL(3,0)) 
RETURNS DECIMAL(18,8)
LANGUAGE SQL
NO EXTERNAL ACTION
DETERMINISTIC
BEGIN ATOMIC
    DECLARE out_num DECIMAL(18,8);
    IF p_sts=0 THEN
        SET (out_num)
               = (SELECT id
                  FROM TABLE
                  WHERE status = p_sts 
                  );
    ELSE
        SET (out_num)
               = (SELECT id
                  FROM TABLE
                  WHERE status = p_sts 
                  AND date <= TO_DATE('2010/12/31','YYYY/MM/DD')
                  AND date >= TO_DATE('2010/12/31','YYYY/MM/DD'));
    END IF;
    RETURN out_num;
END

まあ、こんな関数を大量生産していて。コストは掛かる。遅い。

解決策

使い物にならなかったので、DB2データベースでは、下のようにJava製埋め込みに再作成しました。

stored.java
package jp.co.db2udf.getcontent;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;

public class GetContent extends DBUtil {

    public static BigDecimal get_content(BigDecimal p_id , Timestamp p_date , BigDecimal p_sts ) throws SQLException{       
        BigDecimal out_num = BigDecimal.valueOf(99) ;
        StringBuffer Sql = new StringBuffer();
        String ret = null;
        DBConnect();
        if (p_sts.intValue() == 0) {
            //out_num
            Sql.append("SELECT id ");
            Sql.append("FROM table ");
            Sql.append("WHERE status = "+ p_sts  );
        } else {
            //out_num
            Sql.append("SELECT id ");
            Sql.append("FROM table ");
            Sql.append("WHERE status = " + p_sts );
        Sql.append("  AND sdate <= TIMESTAMP ('2010-12-31-00.00.00.000000') ");
        Sql.append("  AND edate >= TIMESTAMP ('2010-12-31-00.00.00.000000') ");
        };
        ps = con.prepareStatement(Sql.toString());
        rs = ps.executeQuery();
        if(rs.next()){ 
            ret = rs.getString(1);
        } else {
            ret = "0";
        }
        if (ret.equals("") || (ret.equals(null))) {
            ret = "0" ;
        };
        DBDisConnect();
        out_num = new BigDecimal(ret); 
        return out_num;
    }
}

何をやっている関数なのかは、業務上のことなので置いておいて。

execute.sql
select 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0), 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0), 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0), 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0), 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0), 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0), 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0), 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0), 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0), 
 OBJECT_PKG.GET_CONTENT(1, current timestamp, 0)
from dual 
/

改めて測定!

Java化後、測定結果

Before

Access Plan:
-----------
    Total Cost:         29600.3

After:(大雑把に100000000分の1!)

Access Plan:
-----------
    Total Cost:         0.000333947

10カラム実行時

db2 => select
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0),
db2 (続き) =>  object_pkg.get_content(1, current timestamp, 0)
db2 (続き) => from dual
db2 (続き) => /

1                    2                    3                    4
    5                    6                    7                    8
        9                    10
-------------------- -------------------- -------------------- ----------------
--- -------------------- -------------------- -------------------- ------------
------- -------------------- --------------------
          0.00000000           0.00000000           0.00000000           0.0000
000           0.00000000           0.00000000           0.00000000           0.
0000000           0.00000000           0.00000000

  1 レコードが選択されました。

ワーニングが出力されなくなった!
(そんな当たり前のことに 感涙...というか、これがデータベースの差か、と当時衝撃を受けたプロジェクトでした。)

解説

Oracleは10g、DB2はV8.2だった、古き良き当時の思い出話です(計測した数値は実際のものです)。少しだけ解説すると、OracleのSQLは独自に拡張した「PL/SQL」ですが,DB2 UDBは標準SQLだったり。方言の許容度合いがかなり違った。参考:OracleをDB2に変更する際の注意点を知りたい

DB2逆引きWiki 非常にお世話になりました。
移行資料、すでに、だいぶ状況は変わっていますのでご注意をば。あと別にフロントエンドの話じゃなかったですね... :bow:

おまけ

皆様仕事は納まりましたでしょうか。
いますぐ左上に表示されているLGTMの数だけスクワット...ではなくて深く目を閉じて秒数、瞑想してみるのも良いと思います。今年を振り返って。

以上100倍という数値、すごいなあと思いつつ、いやいやいや自分にもこんな思い出があったなあと思いおこした年の瀬の思い出話でした。

e99h2121
2003年新卒入社した「人事給与システムのリーディングカンパニー」でへたこきながら開発をしています。2016aug生まれ娘、2018oct生まれ息子に精神を鍛えられている日々
http://e99h2121.github.io/
works-hi
「はたらく」を楽しく!に向けて大手企業の人事業務から変えていく HR業界のリーディングカンパニー
https://www.works-hi.co.jp/
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
この記事は以下の記事からリンクされています
コメント
この記事にコメントはありません。
あなたもコメントしてみませんか :)
すでにアカウントを持っている方は
ユーザーは見つかりませんでした