連載
» 2008年09月30日 00時00分 公開

Oracle技術者のためのバッチアプリ開発講座(2):DBエンジンを最大限に生かすバッチアプリの作り方 (1/3)

第1回では、バッチアプリケーションを設計するうえで考慮すべき4つのポイントについて解説しました。今回は、Oracleデータベースを最大限に利用したバッチアプリケーションの実装テクニックについて解説します。

[白砂丈太郎,株式会社ワン・オー・ワン]

データベース管理システム=データ加工エンジンと心得よ

 用語辞典などを参照すると、「データベース」という言葉は1950年代に米軍で使われ始めたようです。各地に点在していた膨大な情報を1か所の基地(Base)に集めたことからData Base(データの基地)という言葉が生まれ、ここから「特定のテーマに沿ったデータを集めてコンピュータ上で管理し、容易に検索/抽出などの再利用をできるようにしたもの」という意味を表すようになりました。

※IT用語辞典e-Words:「データベース」、TECHSCORE:「データベースとは? SQL」、ウィキペディア(日本語版):「データベース」などに解説があります。


 このデータベース、皆さんは有効活用されているでしょうか? 普段からOracleなどを扱っている技術者でも、データベースを単なる「データの保管場所」としてしかとらえてない傾向があります。データの加工/集計は外部のプログラム言語で行い、データベースは結果を格納する入れ物としてしか活用していないのです。

 もちろん、データベースを使用する第一の目的は、整合性/トランザクション管理/同時実行制御/機密保護/障害回復などを考慮して、データを安全かつ効率的に保持するためです。しかし、データをただ貯めておくだけでは意味がありません。膨大なデータをさまざまな形に作り変え、業務の効率化や経営判断に役立てることが重要なのです。

 Oracleに代表されるデータベース管理システムは、文字通りのデータ保管庫としての機能だけでなく、データベースを構築するための機能も豊富に提供されています。バッチ処理を構築する上で必要となるデータの加工/集計処理についても、SQLやPL/SQLのレベルで利用可能な機能が数多く実装されています。これらの便利な機能を利用しない手はありません。

 Oracleをデータ加工エンジンとして最大限に活用すれば、バッチアプリケーションの性能は劇的にアップします。つまり、データをプログラムで逐次処理するのではなく、Oracle上で一括処理してしまうのです。こうすれば、通常のバッチ処理では必須となる条件分岐や繰り返し処理といった概念は不要になり、SQLの条件検索で一気に処理することができるのです。

PL/SQLではCOBOL的ロジックを離れよ

 企業で稼働しているバッチアプリケーションの中には、現在でも少なからずCOBOLで書かれたものが存在します。COBOLアプリケーションでは、入力ファイルから読み込んだデータをIF文やEVALUATE文などで1件ずつ評価して条件分岐するようなコーディングが一般的です。

 このようなロジックをそのままOracleのPL/SQLに移行すると、リスト1のようなカーソル(CURSOR)を使用したループ処理になります(入力ファイルのデータは、データベース上のテーブルにロードされているものとします)。

DECLARE
    -- カーソル変数の定義
    CURSOR c1 IS SELECT * FROM t1 ORDER BY key;
    -- フェッチ行を格納するレコード型変数の定義
    r1 t1%ROWTYPE;
BEGIN
    -- カーソルの現在行をフェッチして1件ずつループ処理する
    FOR r1 IN c1 LOOP
        -- key列が5以下の場合、value列を10倍する
        IF r1.key <= 5 THEN
            r1.value := r1.value * 10;
        -- key列が5より大きい場合、value列を20倍する
        ELSE
            r1.value := r1.value * 20;
        END IF;
        -- 更新したレコードを一時テーブルに挿入する
        INSERT INTO t1_temp VALUES r1;
    END LOOP;
    -- 処理を確定する
    COMMIT;
END;
リスト1 カーソルを使用したループ処理

 リスト1のPL/SQLプログラムは、次のような処理を行います。

  1. テーブルt1のレコードを1件ずつ読み込む
  2. key列が5以下の場合はvalue列を10倍し、key列が5より大きい場合はvalue列を20倍する
  3. 更新したレコードを一時テーブルt1_tempに挿入する

カーソルを使用したループ処理は不幸の始まり!?

 カーソルは、実際のレコードの位置を示すポインタのようなものです。複数のレコードを返すSELECT文の実行結果に対しては、このカーソルを使用してアクセスすることができます。また、カーソルが指し示すレコードを1件ずつ順番に取り出す処理のことをフェッチ(FETCH)といいます。

 この「カーソルを使用したループ処理」は、実のところ大量レコードの処理にはまったく向いていません

Oracle内部の実行エンジン切り替え動作を意識しよう

 リスト1のようにPL/SQLプログラムからSQL文を発行する場合、Oracleは実行エンジンをPL/SQLエンジンからSQLエンジンに切り替えて処理します。大量のレコードをカーソルでループ処理すれば、実行エンジンの切り替えもレコード件数に応じて繰り返し発生することになります。この切り替え処理が大きなオーバーヘッドを生み出し、処理性能の悪化につながるのです(図1)。

図1 実行エンジンの切り替え 図1 実行エンジンの切り替え

 このように、COBOLアプリケーションの考え方をそのままデータベースの世界に持ち込んでしまうと、非常に効率の悪いアプリケーションができてしまいます。大量データを扱うバッチアプリケーションでは、よほど複雑な処理を実装する場合を除いて、「カーソルを使用したループ処理を行わない」というポリシーをプロジェクトで共有することをお勧めします。

       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。