PostgreSQL(以下ポスグレ)のVACUUM(バキューム)について調べてみました。
■VACUUMとは
ポスグレ独自のSQLコマンド。ポスグレではUPDATE、DELETE文では物理データの削除は行われず削除フラグをたてるだけで追記していくためどんどんディスクを消費していってしまう。そのため定期的に不要になった領域を回収する必要がある。そのコマンドがVACUUM。■VACUUMとConcurrent VACUUM
VACUUMの処理は削除フラグの立ったデータを物理的に削除するので、その間対象テーブルに全てのアクセスを禁止するロックをかけます。「おいおいそりゃありえないよ」ということでVersion 7.2からはテーブルをロックしない方式に変わりました。(Concurrent VACUUM)
Concurrent VACUUMは共有メモリ上の空き領域マップ(Free Space Map)に削除フラグの立ったデータの位置を記録します。ポスグレはデータを追加する必要が発生した時にこの空き領域マップを参照し、その場所にデータを書き込むためにデータ領域が再利用されます。
そんな方法で領域を再利用するだけなのでCuncurrent VACUUMでは一度大きくなった物理データ量はそれ以上小さくなりません。物理的に使っていない領域を一度削除するにはVersion 7.1以前のVACUUM(VACUUM FULL)を行います。
■なんでこんなことしなきゃいけないんだ
他のRDBMSを使っていると「なんで追記すんの?普通に消してくれよ!」と思うかもしれません。(おれも思いました)しかし、追記型であることの利点も結構あるみたいです。
ポスグレは内部的にはレコードのデータにデータを識別するOID(オブジェクトID)とトランザクションを制御するXID(トランザクションID)をくっ付けて管理しています。新しいトランザクションが発生すると元のデータはそのままにして、OIDはそのままでXIDを一個増やしたデータを追記しようとします。元のデータは放置です。この方法だと同時に来たトランザクションの隔離や制御などがいかにも簡単に実装できそうな気がします。(常にスナップショットを残しているようなものだから)
具体的にユーザー側のメリットとしては”“読み込みロックと書き込みロックが競合しない””というのがあります。「常に追記なんだからたしかに出来そう」という気がします。ポスグレはこの辺をMVCC(Multi Version Concurrency Control:多版型同時実行制御)という方式で実装しているらしいです。