Oracleには処理を高速化するための機能が色々と準備されています。
そのなかで今回は、SQLでバッチ処理を書くときに楽になるような機能を紹介したいと思います。
それはglobal temporary table
です。
特に、global temporary table
のon commit delete rows
で定義されたテーブルの活用について記述します。
参考: 津島博士のパフォーマンス講座 第11回 良いSQLについて(2)
#■概要#
テーブル定義(入れ物)のみ共有して、レコードは登録した人だけが見ることができ、他の人は見ることができません。
セッションやトランザクションの終了時にテーブルデータが自動削除される機能です。
#■説明#
使い方は、普通のテーブルとかわりません。
これから紹介する内容は、イメージはプログラム内の変数「listやmap」
みたいに一時的にデータを保管する機能と思ってもらえればピンとくるでしょうか。
不要になった時、いちいち削除しないでよく、使い捨てが出来ることが良いです。
しかし、利用方法が具体的に説明されてないことが多いためか、あまり活用されていなくて勿体ないと筆者は思っています。(これまで活用している案件に出会ったことがない。)
そのため、筆者は設計にガンガン活用して本番運用をトータル5年ほどの検証を経て有用だと確信したため、みんなにも楽してほしいという思いで記事にすることにしました。
#■構文#
通常のテーブル定義とほとんど一緒です。
create global temporary table テーブル名
(カラム定義ホゲホゲ)
[on commit delete rows | on commit preserve rows]
on commit オプションで一時表のポリシーを設定可能です。
delete rows or preserve rows を指定する。
on commit delete rows
トランザクション終了時にデータを削除する
(セッション終了時もデータを削除してくれます。)
on commit preserve rows
セッション終了時にデータを削除する
#■例#
筆者はこれしか使わない定義オプションon commit delete rows
(コミット発行で消える。セッション終了でもちゃんと消える。)で定義されている前提でいきます。
TBL‗SALESのある条件に合致する伝票番号
をキーに処理することが可能なとき色々注文されて、下記のような処理をするとします。
※伝票番号がTBL‗SALES上でユニーク
という前提です。。
①トランザクション発行
②対象レコードの排他
③更新前レコードの保管
④レコード更新
⑤コミット発行
//①トランザクション発行
//②対象レコードの排他
select 1 from TBL‗SALES where [★煩雑な条件がたくさん] for update nowait
//③更新前レコードの保管
insert into [保管用テーブル名]
select * from TBL‗SALES where [★煩雑な条件がたくさん]
//④レコード更新
update TBL‗SALES set [更新内容] where [★煩雑な条件がたくさん]
//⑤コミット発行
特に仕様変更時、[★煩雑な条件がたくさん]の部分で、条件漏れなどの不具合を散見します。
実行中にデータ更新があると、条件合致するレコードが増えたり減ったりするのも地味にいやらしいです。
##そんなとき##
ここでglobal temporary table
の登場です。
※以降global temporary table
は、グローバルテンプと記述します。
//①トランザクション発行
の後、直ぐにグローバルテンプに対象レコードのキー(伝票番号)をinsertします。
insert into [グローバルテンプテーブル名]
select 伝票番号 from TBL‗SALES where [★煩雑な条件がたくさん]
②③④の処理は、
[★煩雑な条件がたくさん]
の部分を
[伝票番号 in (select tmp.伝票番号 from [グローバルテンプテーブル名] tmp)]
に置き換えるだけです。
⑤コミット発行
グローバルテンプの内容は、自動で削除される。(※ロールバックでも削除されます!)
これで修正時は、グローバルテンプに登録するときの条件をなおすだけで済みますね。
さらにキーの伝票番号がユニークなら、実行速度も速い!
以上が活用例ですが、利用イメージがついて応用してもらえれば幸いです。