今回はVACUUMについて記載します。個人的な意見としまして、PostgreSQLで1番の有名で特徴的な機能な気がします。
#VACUUMを行わなければいけない理由
そもそも、VACUUMはなぜ実施していかなければならないのか?VACUUMを実施する大きな理由は以下の4つです。
- 更新、あるいは削除された行によって利用されているディスク領域の再利用
- PostgreSQL問い合わせプランになによって使用されるデータ統計情報の更新
- インデックスオンリースキャンを高速化するためのVisibility MAPの更新
- トランザクションIDの周回問題に対する対応
PostgreSQLはOracleとは異なり、追記型データベースです。更新、削除のあった行は物理的に削除されず、そのまま残ってしまいます。この不要な領域を再利用可能にするためであったり、内部的な様々なメンテナンスを行うためにVACUUMは必ず実行しなければなりません。
#VACUUMの種類
VACUUMに関しては大きくVACUUM
とVACUUM FULL
の2つの種類が存在します。この2つのVACUUMはまったく異なる働きをします。ざっくりと言うと、不要になった空き領域にフラグを立て、再利用可能にするのがVACUUMであり、削除されていないデータをファイル内で前方に移動し、解放された領域をOSに返す動作をするのがVACUUM FULLです。なので、VACUUMを実行してもOSから見たとき空き領域は増えませんが、VACUUM FULLを実行すれば空き領域が増えるという動作になります。
-
VACUUM
テーブルをスキャンし、新しく挿入または更新されるデータで上書きすることができるように、不要になった空き領域にフラグを立てる。 -
VACUUM FULL
VACUUMとは異なり、削除されていないデータをファイル内で前方にある解放済みの場所へ移動する。移動により解放された領域はOSより解放済みと認識され、再利用可能となる。
#AutoVacuum関連パラメータ
PostgreSQL 8.1よりautovacuum機能が追加されました。以下の条件にてautovacuumが実行されます。(autovacuumが推奨)
自動VACUUMで実行してくれるVACUUMはVACUUM FULLではなく通常のVACUUMです。一般的には__VACUUM FULLはAUTO VACUUMを実行していれば不要__であるといわれております。
AUTO VACUUMに関連するパラメータはautovacuum_vacuum_threshold
とautovacuum_vacuum_scale_factor
となります。この2つのパラメータによってバキュームする対象を決定します。この2つの閾値から算出される値よりもdead tuple(削除、更新により不要となったレコード)が大きくなった場合にAUTO VACUUMの対象となりますが、巨大なテーブルだと1/5がdead tupleにならないとVACUUMされないので、設定値を見直す必要があります。
AUTO VACUUMの関連パラメータは以下のとおりです。(テーブル単位で指定可能)
-
autovacuum_vacuum_threshold
autovaccum実行のしきい値となる、dead tuple(updateやdeleteされた行数)の最小数。(デフォルトは50) -
autovacuum_vacuum_scale_factor
autovaccum実行のしきい値となる、テーブル内でdead tupleとなっているレコード数の割合。(デフォルトは0.2) -
閾値
autovacuum_vacuum_threshold + (テーブル行数 * autovacuum_vacuum_scale_factor) < dead tuple数
#統計情報の更新
AUTO VACUUM処理では、同時に統計情報の更新も行われます。別途ANALYZEコマンドも用意されていますが、こちらも自動処理に任せてしまうのが推奨となります。
AUTO ANALYZEの関連パラメータは以下のとおりです。(テーブル単位で指定可能)
-
autovacuum_analyze_threshold
autoanalyzeのしきい値となる、更新レコードの最小数。(デフォルトは50) -
autovacuum_analyze_scale_factor
autoanalyzeのしきい値となる、テーブル内で更新されたレコード数の割合。(デフォルトは0.1) -
閾値
autovacuum_analyze_threshold + (テーブル行数 * autovacuum_analyze_scale_factor) < 更新レコード数
#VACUUMとVACUUM FULLの違い
ここまで、VACUUMとVACUUM FULL、AUTO VACUUMの話をしてきましたが、VACUUMとVACUUM FULLの違いについて、少し触れたいと思います。
まず、VACUUMですが、VACUUMは先ほどの説明の通り、AUTO VACUUMで実行されるコマンドです。実行しても再利用可能領域はOSへ返されません。一方でDMLなども並列実行可能であり、I/Oの負荷もVACUUM FULLに比べて確実に小さいコマンドです。
一方VACUUM FULLはAUTO VACUUMで実行されません。実行すると再利用可能な領域としてOSへ領域を返しますが、実行はI/Oの負荷が高まり、処理時間も比較的長いです。また、実行中排他ロックをとるので、SELECTも行う事が出来ません。
一般的にAUTO VACUUMが正常に動作していれば、VACUUM FULLを実行する必要は無いと言われており、AUTO VACUUMは設定することを強く推奨されている設定となります。
-
VACUUM
・auto vacuumコマンドで実行されるコマンド
・再利用可能領域をOSへ返却しない
・DML系のコマンドは並列可能 -
VACUUM FULL
・auto vacuumでは実行されない。(明示的な実行が必要。)
・再利用可能領域をOSへ返却する。
-再利用可能領域を圧縮することで、テーブルファイルの容量を最小化していく
-処理対象のテーブルをコピーして実行するため、コピー用のDISK領域が必要となる
-処理が長い
-DISK I/Oへの負荷が高い
・テーブルの排他ロックを取得する
#最後に
PostgreSQLの代表的な処理VACUUMに関して説明しました。VACUUMと正しく付き合う事で、PostgreSQLを常に良い状態に保っていただければと思います。
##次回
文字コードとロケールに関する情報を記載したいと思います。