vacuum (5)

scan_heap

この関数はfull vacuumするときにfull_vacuum_relから実行される。onerelで指定されたテーブルの全てのページを調べ、以下の処理を行う。

  • タプルのcommit status(Xmin)を設定する
  • 削除できるタプルがあるページのリスト(vacuum_pages)を作成する
  • ページの断片化を解消して空き領域を増やせるページのリスト(fraged_pages)を作成する

empty_pagesには空のページ数が設定される。empty_end_pagesにはテーブルの末尾にある連続する空きページ数が設定される。
free_spaceにはテーブル全体で使用されていない領域のサイズが設定される。usable_free_spaceには断片化を解消した結果、使用可能になる領域のサイズが設定される。

(1)作業用のvacpageを作成する。削除するタプルを登録する配列が足りなくならないように、MaxOffsetNumberのタプルが登録できるようにメモリを確保している。vacuum_pagesやfraged_pagesに登録するときは、vacpageのコピーをcopy_vac_pageで作成するが、このときはvacpageに登録されているタプルが登録できるだけのメモリを確保する。(コピー後のオブジェクトの方が小さい)

(2)forループで全てのページを調べる

  • 未初期化のページが見付かったらPageInitでページを初期化して、vacuum_pages, fraged_pagesに登録する。未初期化のページはテーブルにページを追加した後、ページを初期化する前にバックエンドが異常終了したときなどに発生する可能性がある。
  • 空のページが見付かったらvacuum_pages, fraged_pagesに登録する。
  • 上記以外(タプルがあるページ)は、ページ内の全タプルについてHeapTupleStatisfiesVacuumでタプルの状態をチェックする。HEAPTUPLE_DEADだったらvacpageに登録する。また、ページのコピーを作成してコピーページのItemIdのLP_USEDフラグをおろす。(コピーページはページの断片化を解消したときの空き領域を計算するために使う。scan_pageではタプルの削除は実行せず、削除するタプルの情報を集める処理を行うため、ページのコピーを作成してから操作している)

ページに削除できるタプルがあったらvacuum_pagesに登録する。また、ページの断片化を解消して空き領域を増やせる場合はfraged_pagesに登録する。

(3)vacrelstatsに後で使う情報を設定する