vacuum (2)
lazy_vacuum_heap
vacrelstats->dead_tupleに登録されたタプルを、テーブルから削除する。
(1)LockBufferForCleanupでページをロックする
(2)lazy_vacuum_pageでページ内のアイテムを削除する
(3)lazy_record_free_spaceでページの空き領域を登録
(4)ロックを開放
(5)WriteBufferでページをdirtyにする
lazy_vacuum_page
指定されたページのタプルを削除する。
(1)vacrelstats->dead_tupleに登録されたタプルのItemIdのLP_USEDフラグをおろす。
(2)PageRepairFragmentationでページの断片化を修正する
(3)一時テーブルではない場合、log_heap_cleanでWALレコードを出力する
lazy_record_free_space
vacrelstats->free_pages配列にページの空き容量の情報を登録する。
free_pages配列が一杯になった場合、配列から一番容量の少ないページの情報を追い出して登録していく。(heap-based priority queuesというアルゴリズムで一番容量の少ないページが配列の先頭にくるように調整している)
PageRepairFragmentation
ページの断片化を修正する。
(1)ItemId配列を順にチェックして、使用中のアイテムの数(nused)を数える。また、削除するアイテムはunused配列にアイテムの番号を登録する。
(2)使用中のアイテムがない場合(nused == 0)の場合、ページをemptyにする。(ItemIdのlp_lenを0にして、pageのpd_upperを初期化する)
(3)使用中のアイテムがある場合、使用中のアイテムデータのoffsetをitemidbase配列に登録し、offset順にソートする。次にoffset順にデータを並べ変える。
log_heap_clean
ページから複数のタプルを削除したときのWALレコードを出力する。PageRepairFragmentationが作成したunused配列をログとして出力する。複数のタプルを削除した情報を1つのログレコードで出力することにより、ログの容量を少なく抑えている。
以下のように配列をそのままログに出力している。
if (uncnt > 0) { rdata[1].data = (char *) unused; rdata[1].len = uncnt * sizeof(OffsetNumber); }
_bt_check_uniqueのバグ修正
_bt_check_uniqueでbufferをdirtyにするコードは以下で正解だった。
if (nbuf == InvalidBuffer) SetBufferCommitInfoNeedsSave(buf); else SetBufferCommitInfoNeedsSave(nbuf);
http://archives.postgresql.org/pgsql-patches/2005-10/msg00088.php
http://archives.postgresql.org/pgsql-committers/2005-10/msg00177.php