DBエンジンを最大限に生かすバッチアプリの作り方:Oracle技術者のためのバッチアプリ開発講座(2)(2/3 ページ)
第1回では、バッチアプリケーションを設計するうえで考慮すべき4つのポイントについて解説しました。今回は、Oracleデータベースを最大限に利用したバッチアプリケーションの実装テクニックについて解説します。
カーソルもfor文も使わない条件分岐処理を会得せよ
カーソルを使用したループ処理を行わずにリスト1のような条件分岐を行うには、どうしたらよいでしょうか?
結果セットに対して一気にSQLで処理を実行する
大量データを扱うバッチ処理を実装する際には、「データを1件ずつ条件分岐させて処理する」というプログラミング的な発想ではなく、「同一条件のデータを1つの結果セットとして取り出して一括処理する」という視点が必要になります(図2)。
前ページリスト1のカーソルを使用したループ処理は、リスト2のようなSQLに置き換えることができます。
--key列が5以下のレコードは、value列を10倍にして一時テーブルに挿入する INSERT INTO t1_temp SELECT key, value * 10 FROM t1 WHERE key <= 5; --key列が5より大きいレコードは、value列を20倍にして一時テーブルに挿入する INSERT INTO t1_temp SELECT key, value * 20 FROM t1 WHERE key > 5; --処理を確定する COMMIT;
リスト2のSQLでは、次のような処理を行います。
- key列が5以下のレコード群をテーブルt1から抽出し、value列を10倍して一時テーブルt1_tempに挿入する
- key列が5より大きいレコード群をテーブルt1から抽出し、value列を20倍して一時テーブルt1_tempに挿入する
このようにSQLのみで処理を記述すれば、リスト1のような実行エンジンの切り替えが発生しません。Oracleなどのデータベース管理システムでは、結果セットに対する処理を非常に得意としています。大量データを処理するロングトランザクションでは、同一条件のデータを1つの結果セットとして取り出して一括処理することで、処理性能を飛躍的に向上させることができます。
CASE式の使いどころを理解しよう
リスト2のSQLは、CASE式を使用してリスト3のように記述することもできます。
--key列が5以下のレコードは、value列を10倍にして一時テーブルに挿入する --key列が5より大きいレコードは、value列を20倍にして一時テーブルに挿入する INSERT INTO t1_temp SELECT key, CASE WHEN key <= 5 THEN value * 10 ELSE value * 20 END FROM t1; --処理を確定する COMMIT;
CASE式はSQL-92で標準に取り入れられた機能で、SQL内に条件分岐処理を記述する際に使用します。非常に便利な機能の割に、その真価はあまり知られていないかもしれません。CASE式を有効活用することにより、これまでPL/SQLで実装しなければならなかったような複雑な処理をSQLのみで実装することができます。
リスト2ではSQLを2回発行しているのに対し、CASE式を使用したリスト3の場合は1回のSQLで処理を行っています。つまり、リスト2では同じ抽出元テーブルを2回スキャンする必要があるのに対し、CASE式を使用したリスト3の場合は1回のスキャンで済むことになります。また、発行するSQLの数が減るということは、事前に解析する必要のあるSQLの数が減るということです。このように、できるだけ少ないSQLで処理を実装すれば、性能上大きなメリットを得ることができます。
Copyright © ITmedia, Inc. All Rights Reserved.