ALTER TABLE MOVE と ALTER TABLE SHRINK の違い

ALTER 〜 SHRINK SPACE Oracle 10g

結論から言うと、現在のオラクルで SHRINK 操作にセグメントの縮小(HWM の低下)の効果を期待するならば 行移行行連鎖 を解消してから実行したほうがよいだろう。(行連鎖は消すことができないので、ASSM ではどこに連鎖するかは運次第?)

SHRINK 操作は Oracle 10g からの機能であり ONLINE 実行できるなどの特長から非常に有用であるが、弱点がいくつかあるようにみえる。 Oracle 10g R1 においては、それらの弱点を人手で助け、回避することによって、SHRINK による効果は相当に向上すると思われる。近いリリースにおいて、これらの弱点もきっと解決されていることと思う。(Oracle 10g R2 は未検証)

SHRINK と MOVE の特徴

  • ALTER TABLE MOVE の動作イメージは
    ダイレクト・パス・インサート で複製、オリジナルを TRUNCATE TABLE(そしてマニュアル操作で 索引を REBUILD)。
  • ALTER TABLE SHRINK は
    断片化の解消を図る SQLを使ってレコード単位にコミットする DELETE、INSERT カーソル処理 という感じである。

ALTER TABLE SHRINK と ALTER TABLE MOVE の代表的な特徴

比較内容SHRINKMOVE
ONLINE(他の処理と並行) 実行できるか
goodはいいいえ
・SHRINK は行単位に処理を完了させているので RX ロックで良い。
・MOVE は 索引構成表 以外では X ロックが必要になる
参考: 表ロックの種類と相互関係
行移行は解消するかいいえ(格納データに依存)goodはい
・SHRINK は断片化の解消するプロセスにおいて、行の連鎖している状態が一部(運がよければ全部)解消される可能性がある。⇒ SHRINK 時の行移行の解消について
・MOVE は完全な再構築なので行移行はすべて解消される。
ハイウォータマークは下がるかデータ分布に依存goodはい
・SHRINK は大量の行移行および行連鎖が放置された状態ではあまり効果が期待できない。⇒ SHRINK 時のセグメント縮小について
・MOVE は HWM を低下させることができる。
作業には大きな空き領域(データセグメント)が必要かgoodいいえ実データ分以上の空き領域が必要
・SHRINK は処理の方式が行単位で移動が行なわれるため不要。
・MOVE は複製と削除という仕組みになるのでレコード件数に比例した空き領域が必要。
作業には大きな一時表領域(テンポラリセグメント)が必要かgoodいいえはい(索引の状態に依存)
・SHRINK は処理の方式が行単位で移動が行なわれるため不要。
・MOVE は複製と削除という仕組みになるのでインデックスのカラム数とレコード件数に比例した一時表領域が使用される。
大規模な索引のメンテナンスが発生するかgoodいいえはい
・SHRINK は行単位にインデックスも処理されるので発生しない。
・MOVE は ROWID がすべて変更される。テーブルに索引が存在する場合にはすべての索引の再構築 (REBUILD) が必要となる(手動で行う必要がある)。
他の句と併用できるかいいえgoodはい
・SHRINK は 単独で使用する必要がある。MOVE は PCTFREE などの他の属性の変更する句も併用可能。
パーティション表全体に使えるかgoodはいいいえ
・SHRINK は パーティション表でも一度で実行できる。
・MOVE は実データが存在するパーティション、または、サブパーティション1つ1つに対して実行する。

SHRINK 時の行移行の解消について

SHRINK 操作によって行移行が解消することがある。 これは断片化を解消するときに行なわれるレコードデータの移動によるものであり、常に連鎖した状態が解消するわけではない。 断片化の解消(行データの移動)は 物理 ROWID によってハンドリングされているようにみえる。 ( 連鎖行断片 ROWID は使っていない? )

セグメントの縮小、HWM の低下について

適当なスクリプトを作り、振る舞いを眺めて*1いたところでは SHRINK は 物理 ROWID を断片化を解消するための重要な値として利用しているようである。(行断片における 連鎖行断片 ROWID は使っていないようにみえる。データ・ディクショナリに情報が存在しないのだろう。)
あるテーブルが連続したデータブロックから構成されていると仮定した場合、そのテーブルに断片化が発生している場合の SHRINK の振る舞いは ROWID が大きな値から順番に前方の空き領域に詰めているようにしているのではないかと考えられる。

重要な点はセグメントの先頭近くで行移行(または行連鎖)が発生して、実際の格納位置がセグメントの終わり(HWM) に近い位置に連鎖しているとき、その行移行がそのまま残ってしまうようなこと(※)があるという点である。
これは他のすべてのレコードが断片化を解消して連続した空き領域が発生しても HWM の近くある、たった一つの行移行によるデータブロックの占有によって HWM の位置をほとんど下げることができないことをあらわす。⇒ テーブル・フルスキャン時に無駄が多い。

(※) Oracle 10g R1 においての実験の振る舞いからの予想

セグメントの縮小効果が低いときの SHRINK の動作イメージ

また SHRINK は行単位で処理を行なうため MOVE 操作とは異なり、自動セグメント領域管理による PCTUSED に該当するような、しきい値の影響も受けている可能性も考えられる。(未検証)。

これらの点から格納効率とハイウォータマークを下げることにおいて MOVE に相当な優位性があると思われる。

SHRINK 実行時の注意点

使用するための前提

セグメントの縮小ができないケース

  • ファンクション索引、ビットマップ結合索引を使用している場合
  • ON COMMIT マテリアライズド・ビューのマスター表の場合

その他

  • ROWID が変更されるため ROWID マテリアライズド・ビューは再構築しないと整合性が合わなくなる。
 


断片化と SHRINK 関連事項

  • SHRINK が実行可能なスキーマ
    テーブル(パーティション表 を含む)、インデックス構成表(オーバーフローを含む)、インデックス
    LOB セグメント、マテリアライズド・ビュー(〜・ログ含む)
日本オラクル
■ 日本オラクル 株式会社
■ オラクルマスター資格 (オラクルマスターとは
■ オラクルサポートセンター

*1 ダンプしたわけではなく ROWID を作業前後でトレースした