Pivotal Knowledge Base

フォローする

Vacuum と Vacuum Full の解説

目的

以下のドキュメントで、実例を添えて、vacuum と vacuum full がどのように動作するか解説する。

定義

Vacuum :

Vacuum が実行されると、デッドスペースが再生されて、同一オブジェクトやテーブル等によって再利用することを可能とする。

Vacuum Anlayze :

VACUUM を実行した後、各々の指定テーブルに対して ANALYZE を実行する。

Vacuum Full :

Vacuum に Full というキーワードを付与すると、全てのテーブルの内容を新しいディスクファイルに書き出し、無駄な領域を開放して OS に返却する。この操作はテーブルに対してテーブルレベルロックを取得しパフォーマンスに甚大な影響を与えるため、高負荷システムにおいては実施をさけるべきものである。

どのように Vacuum は動作するのか?

Vacuum 実行時、greenplum(実質、postgres)は FSM(Free Space Map)を更新、空き領域の追跡情報を維持し、リレーションに基づき引き続き発生する更新は内部テーブルを介して FSM を追跡、必要に応じてそれらを利用する。この際、Vacuum Verbose を実行すると、以下のような情報が取得できる。

INFO:  "vacuum_test": removed 1333496 row versions in 2127 pages  (seg17 sdw3:11039 pid=18570)
INFO:  "vacuum_test": removed 1333104 row versions in 2126 pages  (seg2 sdw1:11036 pid=10693)
INFO:  "vacuum_test": found 1333496 removable, 583324 nonremovable row versions in 3048 pages  (seg17 sdw3:11039 pid=18570)
DETAIL:  0 dead row versions cannot be removed yet.
.........
..........
INFO:  "vacuum_test": removed 1333212 row versions in 2123 pages  (seg1 sdw1:11035 pid=10687)
INFO:  "vacuum_test": found 1333212 removable, 583639 nonremovable row versions in 3048 pages  (seg1 sdw1:11035 pid=10687)
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
2124 pages contain useful free space.
0 pages are entirely empty.

FSM が特定のレベルに達した際には、マスターログ上に報告される。当該レベルは、"max_fsm_relations"(デフォルト値: 1000)や "max_fsm_pages"(デフォルト値: 200000)といったパラメーターで設定可能である。

注意: 仕様上、"max_fsm_pages" は、"max_fsm_relations" 値の 16 倍を超える値でなくてはいけない。そうしないと、データベースは起動しないであろう。

実例

VACUUM と VACUUM FULL の定義を念頭に、実際にそれらを実行し、動作の違いを確認してみよう。

-- VACUUM

  • テストテーブルの作成。
gpadmin=# create table vacuum_test ( a int , b text ) ;
NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Greenplum Database data distribution key for this table.
HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
CREATE TABLE
Time: 359.060 ms
gpadmin=#
  • テストテーブルのタプルとページの値を確認。
gpadmin=#
gpadmin=# select relname , relpages , reltuples from pg_class where relname='vacuum_test';
   relname   | relpages | reltuples
-------------+----------+-----------
 vacuum_test |        0 |         0
(1 row)
Time: 2.438 ms
gpadmin=#
gpadmin=# select * from gp_toolkit.gp_bloat_diag where bdirelid=359758;
 bdirelid | bdinspname | bdirelname | bdirelpages | bdiexppages | bdidiag
----------+------------+------------+-------------+-------------+---------
(0 rows)
Time: 25.589 ms
gpadmin=#
  • テストデータを挿入。
gpadmin=# insert into vacuum_test values (generate_series(1,10000000),'this is a test');
INSERT 0 10000000
Time: 6245.503 ms
gpadmin=# insert into vacuum_test values (generate_series(1,10000000),'this is a test');
INSERT 0 10000000
Time: 4697.305 ms
gpadmin=# insert into vacuum_test values (generate_series(1,10000000),'this is a test');
INSERT 0 10000000
Time: 4319.884 ms
gpadmin=#
gpadmin=#
  • 現段階でのテーブルの使用状況を確認(タプル単位、ページ単位)。
gpadmin=# select relname , relpages , reltuples from pg_class where relname='vacuum_test';
   relname   | relpages |  reltuples
-------------+----------+-------------
 vacuum_test |    15912 | 1.00086e+07
(1 row)
Time: 2.585 ms
  • 正確なデータを得るためテーブルに対して analyze を実行。
gpadmin=# analyze vacuum_test ;
ANALYZE
Time: 1789.892 ms
gpadmin=# select relname , relpages , reltuples from pg_class where relname='vacuum_test';
   relname   | relpages |  reltuples
-------------+----------+-------------
 vacuum_test |    47710 | 3.00096e+07
(1 row)
Time: 2.687 ms
gpadmin=#
  • いくつかの行を削除。
gpadmin=# delete from vacuum_test  where a<800000;
DELETE 2399997
Time: 967.301 ms
                                                  ^
gpadmin=# delete from vacuum_test  where a<8000000;
DELETE 21600000
Time: 2184.398 ms
  • テーブルに対して analyze を実行。
gpadmin=# select * from gp_toolkit.gp_bloat_diag where bdirelid=359758;
 bdirelid | bdinspname | bdirelname | bdirelpages | bdiexppages | bdidiag
----------+------------+------------+-------------+-------------+---------
(0 rows)
Time: 26.318 ms
gpadmin=# analyze vacuum_test ;
ANALYZE
Time: 1881.765 ms
gpadmin=# select * from gp_toolkit.gp_bloat_diag where bdirelid=359758;
 bdirelid | bdinspname | bdirelname  | bdirelpages | bdiexppages |              bdidiag
----------+------------+-------------+-------------+-------------+------------------------------------
   359758 | public     | vacuum_test |       47710 |        7763 | moderate amount of bloat suspected
(1 row)
Time: 19.336 ms
  • テーブルに対して vacuum を実行。
gpadmin=# vacuum vacuum_test ;
VACUUM
Time: 132.314 ms

ここでは、vacuum によってテーブルからいかなる領域も開放されないことが分かる。当該テーブルは依然として vacuum 実行前と同一の OS ブロックを使用している。

gpadmin=# select * from gp_toolkit.gp_bloat_diag where bdirelid=359758;
 bdirelid | bdinspname | bdirelname  | bdirelpages | bdiexppages |              bdidiag
----------+------------+-------------+-------------+-------------+------------------------------------
   359758 | public     | vacuum_test |       47710 |        8057 | moderate amount of bloat suspected
(1 row)
Time: 18.026 ms
gpadmin=# select oid,relname , relpages , reltuples from pg_class where relname='vacuum_test';
  oid   |   relname   | relpages | reltuples
--------+-------------+----------+-----------
 359758 | vacuum_test |    47710 |     6e+06
(1 row)
Time: 1.606 ms
gpadmin=#
  • テーブルに対して analyze を実行しても同様に vacuum 実行前と同様の値をレポートし、"gp_bloat_diag" も同様にテーブルが肥大化していることをレポートしている。
gpadmin=# analyze vacuum_test ;
ANALYZE
Time: 1176.675 ms
gpadmin=# select oid,relname , relpages , reltuples from pg_class where relname='vacuum_test';
  oid   |   relname   | relpages |  reltuples
--------+-------------+----------+-------------
 359758 | vacuum_test |    47710 | 5.80361e+06
(1 row)
Time: 2.638 ms
gpadmin=# select * from gp_toolkit.gp_bloat_diag where bdirelid=359758;
 bdirelid | bdinspname | bdirelname  | bdirelpages | bdiexppages |              bdidiag
----------+------------+-------------+-------------+-------------+------------------------------------
   359758 | public     | vacuum_test |       47710 |        7793 | moderate amount of bloat suspected
(1 row)
Time: 17.707 ms
gpadmin=#
gpadmin=#
  • すでに vacuum が実行された当該テーブルにデータを追加。
gpadmin=# insert into vacuum_test values (generate_series(1,10000000),'this is a test');
INSERT 0 10000000
Time: 5171.964 ms
  • Insert 文を実行した結果、すでにテーブルから解放された領域を再利用し、OS から追加で新たなページをを使用していなかったことが分かる。
gpadmin=# select * from gp_toolkit.gp_bloat_diag where bdirelid=359758;
 bdirelid | bdinspname | bdirelname  | bdirelpages | bdiexppages |              bdidiag
----------+------------+-------------+-------------+-------------+------------------------------------
   359758 | public     | vacuum_test |       47710 |        8057 | moderate amount of bloat suspected
(1 row)
Time: 16.548 ms
gpadmin=# select oid,relname , relpages , reltuples from pg_class where relname='vacuum_test';
  oid   |   relname   | relpages | reltuples
--------+-------------+----------+-----------
 359758 | vacuum_test |    47710 |     6e+06
(1 row)
Time: 1.509 ms
gpadmin=# analyze vacuum_test ;
ANALYZE
Time: 1734.669 ms

gpadmin=# select * from gp_toolkit.gp_bloat_diag where bdirelid=359758;
 bdirelid | bdinspname | bdirelname | bdirelpages | bdiexppages | bdidiag
----------+------------+------------+-------------+-------------+---------
(0 rows)
Time: 16.291 ms
gpadmin=# select oid,relname , relpages , reltuples from pg_class where relname='vacuum_test';
  oid   |   relname   | relpages |  reltuples
--------+-------------+----------+-------------
 359884 | vacuum_test |    47710 | 1.62695e+07
(1 row)
Time: 1.612 ms
gpadmin=#

-- VACUUM FULL

Vacuum full を実行すると、今度はデータは再構成され、使用しない領域は OS に返却される。

gpadmin=# vacuum full vacuum_test ;
NOTICE:  'VACUUM FULL' is not safe for large tables and has been known to yield unpredictable runtimes.
HINT:  Use 'VACUUM' instead.
VACUUM
Time: 1452.043 ms
gpadmin=# select * from gp_toolkit.gp_bloat_diag where bdirelid=359758;
 bdirelid | bdinspname | bdirelname | bdirelpages | bdiexppages | bdidiag
----------+------------+------------+-------------+-------------+---------
(0 rows)
Time: 17.503 ms
 
gpadmin=# select oid,relname , relpages , reltuples from pg_class where relname='vacuum_test';
  oid   |   relname   | relpages | reltuples
--------+-------------+----------+-----------
 359758 | vacuum_test |     9552 |     6e+06
(1 row)
Time: 1.452 ms
gpadmin=#

注意: サイズが非常に大きいテーブルに対して vacuum full を実行すると、想定以上に時間がかかることがある上、その間、当該テーブルに対して排他ロックを取得してしまう。テーブルを再構成するための、より高速な代替手段としては、こちらで示されているようなコマンドでテーブルの再構成を行うか、CTAS を実行、あるいはバックアップ・リストアの実施があげられる。

コメント

Powered by Zendesk