PostgreSQLのVACUUM/REINDEXでDBのサイズが減るか実験

PostgreSQLで定常的に必要なメンテナンスと言えば、「VACUUM(FULL)」が挙げられる。

運用上は「REINDEX」も大事なので、REINDEXによりDBのサイズが変化するのを試してみた。

それぞれの動作はドキュメントを参照(バージョンは実験環境に合わせてあるため8.4)。


VACUUM
http://www.postgresql.jp/document/8.4/html/sql-vacuum.html

REINDEX
http://www.postgresql.jp/document/8.4/html/sql-reindex.html
http://www.postgresql.jp/document/8.4/html/routine-reindex.html


環境は以下の通り。

CentOS 6.5
PostgreSQL 8.4



実験用DBを作成

$ createdb reindex-test
$ psql reindex-test
reindex-test=> 
CREATE TABLE test(
  id      serial    PRIMARY KEY,
  dep_id  integer   default 0,
  name    text      default ''
);
CREATE INDEX idx__test__dep_id ON test (dep_id);
CREATE INDEX idx__test__name   ON test (name);


適当に10万件データをINSERTする。

$ cat ins.sh
#!/bin/sh

for i in `seq 1 100000`
do
  DEP_ID=`expr $RANDOM % 100`
  NAME=`uuidgen | tr -d '-'`
  psql -c "INSERT INTO test (name, dep_id) VALUES ('${NAME}', ${DEP_ID});" reindex-test
done

データ件数を確認。

reindex-test=> SELECT COUNT(*) FROM test;
 count
--------
 100000


サイズを取得。

reindex-test=> SELECT pg_database_size('reindex-test');
 pg_database_size
------------------
         26179344


10万件データをUPDATEする。

$ cat upd.sh
#!/bin/sh

for i in `seq 1 100000`
do
  DEP_ID=`expr $RANDOM % 100`
  NAME=`uuidgen | tr -d '-'`
  psql -c "UPDATE test SET dep_id=${DEP_ID}, name='${NAME}' WHERE id=${i};" reindex-test
done


再びサイズを取得。

reindex-test=> SELECT pg_database_size('reindex-test');
 pg_database_size
------------------
         35682064


VACUUMしてみる。

reindex-test=> VACUUM;
reindex-test=> SELECT pg_database_size('reindex-test');
 pg_database_size
------------------
         35610628


サイズが減った。もう1回。

reindex-test=> VACUUM;
reindex-test=> SELECT pg_database_size('reindex-test');
 pg_database_size
------------------
         35610628

サイズは変わらない。何度か実行しても変わらない。


次に、VACUUM FULL を実行。

reindex-test=> VACUUM FULL;
reindex-test=> SELECT pg_database_size('reindex-test');
 pg_database_size
------------------
         35618820

サイズが増えた。もう一度実行。

reindex-test=> VACUUM FULL;
reindex-test=> SELECT pg_database_size('reindex-test');
 pg_database_size
------------------
         35618820

サイズは変わらない。何度か実行しても変わらない。


REINDEX してみる。

reindex-test=> REINDEX TABLE test;

サイズを確認。

reindex-test=> SELECT pg_database_size('reindex-test');
 pg_database_size
------------------
         24319760

何度かREINDEXしても、サイズは同じ。
VACUUM/VACUUM FULLしても、サイズは変わらない。



まとめ

INSERT直後:26179344(25MB)
UPDATE直後:35682064(34MB)
VACUUM直後:35610628(34MB)
VACUUM FULL直後:35618820(34MB)
REINDEX直後:24319760(23MB)