空コミットとは、あるトランザクションでDMLの実行は無いがコミットする、ことを指す。一般的に通用する用語かどうかは謎だが、ひとまずこのエントリ内ではそういうもんとして話を進める。
Oracleでコレがどういう時に現れるかというと、たとえばFOR UPDATE句を多用するシステムが考えられる。トランザクションの終わりで必ずコミットさせるようにして、ロックの解放漏れを防ぐのが目的である。
何もコミットするものがなければREDOログは発生しないハズなので、空コミットの負荷はほとんど無いと考えられる。が、実際どんなもんなのかをやってみるのが、このエントリの趣旨である。
環境
やること
3種類のPL/SQLを用意し、それぞれの実行時間を計測する。3種類とは、SELECTのみ・COMIITのみ・SELECT + COMMITで、それぞれを100万回実行する。
計測用プログラム
下記は、SELECT + COMMITの100万回ループのパターン。SELECTのみ・COMIITのみは、下記コード中にあるとおり対象行をコメントアウトする。
下記コードのSELECTは、クエリの実行はするがなるべくOracleに負荷をかけないもの、としてこのようなクエリにした。
create or replace PROCEDURE BLANK_COMMIT AS INTO_1 INT; BEGIN FOR I IN 1..1000000 LOOP SELECT 1 INTO INTO_1 FROM DUAL;--COMMITのみのとき、この行をコメントアウトする COMMIT;--SELECTのみのとき、この行をコメントアウトする END LOOP; END BLANK_COMMIT;
また、計測用プログラム実行前に、下記のようにして手動ログスイッチ&バッファキャッシュのクリアをしている。
ALTER SYSTEM SWITCH LOGFILE; ALTER SYSTEM FLUSH BUFFER_CACHE;
実行結果
種類 | 1 | 2 | 3 |
---|---|---|---|
select | 39.125 | 39.000 | 39.031 |
commit | 26.328 | 26.312 | 26.344 |
select + commit | 66.765 | 66.844 | 66.781 |
感想とか
おおむね空コミットの負荷はきわめて小さい、と考えられる。
この環境では、100万回の空コミットにつき約26秒かかっている。大雑把に言えば、100万回のトランザクションにつき空コミットをしない場合に比べれば約26秒損している、と言える。1トランザクションあたりでは0.000026秒の損なので、これはまぁほとんど無いと見なしても良いんではなかろうか。
コミットはしてもREDOログが無ければ、コミットの負荷はほぼCPUの性能依存となると思われる。ウチのOracleマシンはかなりショボイので、より性能の良いマシンであればこの差はもっと小さくなるハズである。この点からも、空コミットの負荷はほとんど無いんじゃないかなぁ、と推測される。
つづき⇒Oracleの空コミットは別セッションのトランザクションに影響を与えるか - kagamihogeの日記
2014/03/03追記
「Oracleの空コミット負荷は気にしなくても良い」をどこで読んだ知識なのか発見した。
COLUMN:空コミットはしないほうが良いですよね?
Oracleは、いわゆる空コミットやSELECTFOR UPDATE以外の問い合わせのみ実行していた場合には、読み取り専用トランザクションの扱いとなり、REDOログファイルに対して書き込みを待機する実際のコミット処理は行ないません。そのため、空コミットが増えることはデータベース全体に対する懸念材料にはなりません。user commits統計値にも反映されません。
門外不出のOracle現場ワザ 第5章
ソースコード&statspackレポート
statspackレポート取得して比較しようと思ったけど、めんどくなってやめてしまった。
https://github.com/kagamihoge/oraclestudy/blob/master/plsql/blankcommit/BLANK_COMMIT.sql
https://github.com/kagamihoge/oraclestudy/tree/master/statspackrepots/blankcommit