トランケートについて知っておくべきこと [SQL・DDL]

#変更履歴:2019/5/3 図を追加

トランケートをご存知だろうか。こんな単純な問いかけに対し自信をもって「はい」と答えられるDBAは以外と少ないかもしれないと最近思い始めている。

まずはじめに基本的な事項をおさらいしておこう。トランケートはテーブル(パーティション)内のレコードを削除するDDLである。HWM(ハイウォーターマーク)を下げることにより、テーブル内のレコードを削除するため、一般的にDELETEより高速であり、ログ量も小さくて済む。また、DDLであるため、ロールバックはできない。

 例)truncate table scott.emp

トランケートはreuse storageオプションがある。これをつけると、確保済みエクステントを開放せず、保持しながらトランケートを実行することができる(下記例)。デフォルトはdrop storageである。

 例)truncate table scott.emp reuse storage

パーティションレベルのトランケートは上記reuse storageオプションの他、(パーティション)索引のリビルド・パラレル等のオプションが指定できる。

 例)alter table scott.emp truncate partition part01 (..オプション)

いかがだろうか。これだけでも、トランケート処理は様々な機能が実装されていることがわかると思う。さて、このトランケートの挙動について知っておいた方がよいと思うことを以下に5点述べる。11gR2の挙動をベースに記載しているが、バージョンが違っても基本的なアーキテクチャは大きく変わっていないので12cでも参考になるだろう。

その1.共有カーソルが無効化されハードパースが走る

トランケートを実行すると、その対象セグメントのDATA_OBJECT_ID(セグメントのオブジェクト番号)が変更される。これにより、当該オブジェクトにかかわるSQLの共有カーソルがINVALIDになる(RACでは全ノードで関連するSQLがINVALIDとなる)。この結果、次回SQL実行時にハードパースが走ることになる。なお、パーティション表の場合は、仮に1つのパーティションをトランケートしても、すべてのパーティション、およびテーブルのDATA_OBJECT_IDが変更される点である。このため、参照していないと思ってトランケートすると、ハードパースによりオンラインのSQLに思わぬ性能劣化を発生させてしまうということが起こりうる。

なお、ALTER TABALEやALTER INDEXといったDDLでも同様の挙動が発生する。どのような処理で共有カーソルがINVALIDになるかについては、「共有カーソルがINVALIDになる処理(KROWN:101305)(ドキュメントID 1731739.1)が参考になるだろう。

1.JPG


その2.テーブルレベルのロックがかかる

特定のパーティションのトランケートでも、共有カーソルを無効化するため、テーブルレベルでlibrary cache lockを排他モードで獲得する。このとき、ハードパースが必要なSQLはlibrary cache lockを共有モードで獲得する必要があるため、待ちが発生する。この理由から、異なるパーティションのトランケート処理を並列実行したとしても、処理は必ずシリアライズされてしまう。

2.JPG


その3.ミニ・チェックポイントが走る

トランケートを実行すると、内部でミニ・チェックポイント(バッファキャッシュ上のダーティブロックをストレージに書き出す処理)が走る。このため、バッファキャッシュ上のダーティブロックが多いと、トランケート処理時間が長くかかることがある。この事象が発生するときは、enq: RO fast object reuseの待機イベントが顕著に表れる。

3.JPG


その4.reuse storageを付けると遅くなることがある

reuse storageはエクステントの開放はしないが、空ブロックであるというマークをする必要があるため、エクステント数とブロック数に応じてトランケート時間が伸びる傾向がある。INSERT時のエクステント確保の性能とのトレードオフに考慮が必要だが、筆者のExadataでの経験上では、reuse storageなしの方が速い。

その5.グローバル索引のメンテナンスが必要

パーティションをトランケートすると、グローバル索引はunusable(再構築までアクセス不可)状態となる。しかし、update global indexesオプションを付与すると、グローバル索引の自動更新が可能である。

 例)alter table scott.emp truncate partition part01 update global indexes

一見便利であるが、この処理の内部的にはフルテーブルスキャンが走る(ドキュメントID 2177233.1)ため、テーブル全体の件数に応じて時間がかかる。運用当初は少ないパーティションでレコード数が小さくから顕在化しにくいが、経年で大きくなると非常に時間がかかるようになることがありうるため注意が必要である。このフルスキャンはparallel句を付けることでパラレル度を上げることができるが、おそらくこれが唯一のチューニング方法だろう。

4.JPG


上記5点を踏まえると、トランケート関連のトラブルを避ける上では以下に注意すればよいだろう。

・業務繁忙時間帯にトランケートを実行することは極力避ける
・reuse storageはむやみに使わない(トランケートだけなら使わないほうが性能は良い)
・グローバル索引は極力作らない(作るならメンテナンスの方式を考えておくこと)
・トランケートの発行回数は極力減らす。例えば、パーティション単位でなく、テーブル単位でまとめてトランケートする(下図)

5.JPG


トランケートについて理解を深めるきっかけになれば幸いである。
nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。