OSS Fan ~OSSでLinuxサーバ構築~

このエントリーをはてなブックマークに追加

PostgreSQLでVACUUMの実行により不要領域を回収

カテゴリ:OSSセットアップ | ソフトウェア:PostgreSQL | タグ:
最終更新日:2020/12/30 | 公開日:2013/09/26

目次

概要

 PostgreSQLで、データの更新(update)、削除(delete)を行うと 変更前のデータは物理的には消されずに残り続けます。 イメージ的にはupdateを行った場合、delete+insertが実行されたとの 同じになります。deleteはデータに削除マークを付けただけで、 データは消去されません。 その結果、データの更新を行い続けるとデータベースファイルのサイズが どんどん大きくなっていきます。 この問題を解消するために、PostgreSQLではVACUUMという機能を持っており、 これを実行することで、消されずに残り続けている不要領域を回収し、 次のinsertやupdateが実行された際に、回収した領域を再利用できるようにします。

 ただ、実は初期状態でも自動でVACUUM処理が実行される設定になっているため、 VACUUMを明示的に実行しなくても問題になることは少ないと言えます。

 ここでは手動でVACCUM処理を実行する方法を紹介します。 VACUUMには大きく分けてVACUUMとVACUUM FULLの2種類があります。 名前はちょっとした違いで、実行方法も同等ですが、動作は大きく異なっています。 それぞれについて実行方法を示します。

構成

サーバ構成

OSバージョン

Red Hat Enterprise Linux 5.9 x86_64

パッケージ一覧

postgresql90-9.0.8-1PGDG.rhel6.x86_64.rpm
postgresql90-libs-9.0.8-1PGDG.rhel6.x86_64.rpm
postgresql90-server-9.0.8-1PGDG.rhel6.x86_64.rpm

手順

VACUUMの実行

 VACUUMではテーブルの削除マークが付いた領域を回収し、 insertやupdateの際に再利用できるようにします。 VACUUMでは排他ロックが取得されないため、 VACUUMを実行しながら並行してテーブルの読み書きを実行することができます。

1テーブルのVACUUM

 テーブルを指定してVACUUMを実行する場合、テーブルの所有者、もしくは スーパーユーザで実行します。

 以下の例では、user1 ユーザでデータベース testdb1 に接続し、 tbl1 テーブルをVACUUMしています。

-bash-3.2$ psql -U user1 testdb1
ユーザ user1 のパスワード: ←データベースユーザ user1 のパスワードを入力
psql (9.0.13)
"help" でヘルプを表示します.

testdb1=> \dt
         リレーションの一覧
 スキーマ | 名前 |    型    | 所有者
----------+------+----------+--------
 public   | tbl1 | テーブル | user1
(1 行)

testdb1=> vacuum tbl1;
VACUUM
testdb1=>

データベース内の全テーブルのVACUUM

 テーブルを指定せずにVACUUMを実行すると、データベース内の 全テーブルがVACUUMされます。 一般ユーザでは共有カタログをVACUUMすることができませんので スーパーユーザで実行します。

 以下の例では、スーパーユーザである postgres ユーザでデータベース testdb1 に接続し、 共有カタログを含む全テーブルをVACUUMしています。

-bash-3.2$ psql -U postgres testdb1
ユーザ postgres のパスワード: ←データベースユーザ postgres のパスワードを入力
psql (9.0.13)
"help" でヘルプを表示します.

testdb1=# \dt
 public   | tbl1 | テーブル | user1

testdb1=# vacuum;
VACUUM
testdb1=>

 スーパーユーザ以外で実行した場合は、以下のように 警告が出力され、共有カタログをVACUUMすることができません。 ただし、共有カタログを除くテーブルだけはVACUUMできます。

testdb1=> vacuum;
WARNING:  skipping "pg_authid" --- only superuser can vacuum it
WARNING:  skipping "pg_database" --- only superuser can vacuum it
WARNING:  skipping "pg_db_role_setting" --- only superuser can vacuum it
WARNING:  skipping "pg_tablespace" --- only superuser can vacuum it
WARNING:  skipping "pg_pltemplate" --- only superuser can vacuum it
WARNING:  skipping "pg_auth_members" --- only superuser can vacuum it
WARNING:  skipping "pg_shdepend" --- only superuser can vacuum it
WARNING:  skipping "pg_shdescription" --- only superuser can vacuum it
VACUUM

VACUUM FULLの実行

 VACUUM FULLでは不要領域回収後にデータファイルを縮小します。 VACUUM FULLでは実行時に排他ロックが取得されます。 そのため、実行が終了するまで対象テーブルの読み書きは待たされます。 また、VACUUMと比較して実行に時間がかかります。

1テーブルのVACUUM FULL

 テーブルを指定してVACUUM FULLを実行する場合も、VACUUMの場合と同様に テーブルの所有者、もしくはスーパーユーザで実行します。

 以下の例では、user1 ユーザでデータベース testdb1 に接続し、tbl1 テーブルをVACUUM FULLしています。

-bash-3.2$ psql -U user1 testdb1
ユーザ user1 のパスワード: ←データベースユーザ user1 のパスワードを入力
psql (9.0.13)
"help" でヘルプを表示します.

testdb1=> \dt
         リレーションの一覧
 スキーマ | 名前 |    型    | 所有者
----------+------+----------+--------
 public   | tbl1 | テーブル | user1
(1 行)

testdb1=> vacuum full tbl1;
VACUUM
testdb1=>

データベース内の全テーブルのVACUUM

 テーブルを指定せずにVACUUM FULLを実行すると、データベース内の 全テーブルがVACUUMされます。 一般ユーザでは共有カタログをVACUUMすることができませんので スーパーユーザで実行します。

 以下の例では、スーパーユーザである postgres ユーザでデータベース testdb1 に接続し、 共有カタログを含む全テーブルをVACUUM FULLしています。

-bash-3.2$ psql -U postgres testdb1
ユーザ postgres のパスワード: ←データベースユーザ postgres のパスワードを入力
psql (9.0.13)
"help" でヘルプを表示します.

testdb1=# \dt
 public   | tbl1 | テーブル | user1

testdb1=# vacuum full;
VACUUM
testdb1=>

 スーパーユーザ以外で実行した場合は、以下のように 警告が出力され、共有カタログをVACUUMすることができません。 ただし、共有カタログを除くテーブルだけはVACUUMできます。

testdb1=> vacuum full;
WARNING:  skipping "pg_authid" --- only superuser can vacuum it
WARNING:  skipping "pg_database" --- only superuser can vacuum it
WARNING:  skipping "pg_db_role_setting" --- only superuser can vacuum it
WARNING:  skipping "pg_tablespace" --- only superuser can vacuum it
WARNING:  skipping "pg_pltemplate" --- only superuser can vacuum it
WARNING:  skipping "pg_auth_members" --- only superuser can vacuum it
WARNING:  skipping "pg_shdepend" --- only superuser can vacuum it
WARNING:  skipping "pg_shdescription" --- only superuser can vacuum it
VACUUM