【PostgreSQL 12 新機能】pg_stat_progress_create_index と pg_stat_progress_cluster を検証してみた

こんにちは。サイオステクノロジー OSS サポート担当 Y です。

今回は PostgreSQL 12 (現時点ではまだ beta 版) で追加される予定の統計情報ビューである pg_stat_progress_create_index 及び pg_stat_progress_cluster について検証してみました。(※以下の内容は CentOS 7.6/PostgreSQL 12beta2 にて検証しています。)

■はじめに

次の PostgreSQL のメジャーバージョンである PostgreSQL 12 では、複数の機能追加/強化が予定されています。今回は PostgreSQL 12beta2 を使って、pg_stat_progress_create_index と pg_stat_progress_cluster の検証を実施してみました。

pg_stat_progress_create_index では CREATE INDEX コマンドの進捗状況を、pg_stat_progress_cluster では VACUUM FULL と CLUSTER コマンドの進捗状況をそれぞれ確認することが可能です。

■検証

それでは、さっそく検証してみます。

まずは、以下の様に検証用のテーブルを作成します。

postgres=# SELECT version();
                                                  version                                                   
------------------------------------------------------------------------------------------------------------
 PostgreSQL 12beta2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
(1 row)

postgres=# 
postgres=# CREATE TABLE test (a int);
CREATE TABLE
postgres=# 
postgres=# INSERT INTO test VALUES (generate_series(1, 3000000));
INSERT 0 3000000
postgres=# 

では、このテーブル test に INDEX を作成しつつ、pg_stat_progress_create_index で進捗状況を確認してみます。

“SELECT * FROM pg_stat_progress_create_index” をループ実行しつつ、別のターミナルで CREATE INDEX 文を実行してみます。

[ターミナル 1]
postgres=# CREATE INDEX ON test (a);
CREATE INDEX
[ターミナル 2]
postgres=# \x
Expanded display is on.
postgres=# 
postgres=# SELECT * FROM pg_stat_progress_create_index;
(0 rows)

postgres=# 
postgres=# \watch 1
(0 rows)

Fri Jul  5 08:23:13 2019 (every 1s)

-[ RECORD 1 ]------+-------------------------------
pid                | 80
datid              | 12674
datname            | postgres
relid              | 16400
index_relid        | 0
command            | CREATE INDEX
phase              | building index: scanning table
lockers_total      | 0
lockers_done       | 0
current_locker_pid | 0
blocks_total       | 13275
blocks_done        | 9577
tuples_total       | 0
tuples_done        | 0
partitions_total   | 0
partitions_done    | 0

Fri Jul  5 08:23:14 2019 (every 1s)

-[ RECORD 1 ]------+---------------------------------------
pid                | 80
datid              | 12674
datname            | postgres
relid              | 16400
index_relid        | 0
command            | CREATE INDEX
phase              | building index: loading tuples in tree
lockers_total      | 0
lockers_done       | 0
current_locker_pid | 0
blocks_total       | 0
blocks_done        | 0
tuples_total       | 3000000
tuples_done        | 1966204
partitions_total   | 0
partitions_done    | 0

Fri Jul  5 08:23:15 2019 (every 1s)

-[ RECORD 1 ]------+---------------------------------------
pid                | 80
datid              | 12674
datname            | postgres
relid              | 16400
index_relid        | 0
command            | CREATE INDEX
phase              | building index: loading tuples in tree
lockers_total      | 0
lockers_done       | 0
current_locker_pid | 0
blocks_total       | 0
blocks_done        | 0
tuples_total       | 3000000
tuples_done        | 3000000
partitions_total   | 0
partitions_done    | 0

(0 rows)

(0 rows)

すると、上記の様に INDEX 作成の進捗情報を確認することができました。

次に、pg_stat_progress_cluster を検証してみます。

VACUUM FULL の検証を実施するために、先に適当な更新処理及び VACUUM を実施して再利用可能な領域 (VACUUM FULL で処理する領域) を発生させておきます。

postgres=# UPDATE test SET a = 1 WHERE a % 2 = 0;
UPDATE 1500000
postgres=# 
postgres=# VACUUM test;
VACUUM

この状態で “SELECT * FROM pg_stat_progress_cluster” をループ実行しつつ、別のターミナルで VACUUM FULL 文を実行してみます。

[ターミナル1]
postgres=# VACUUM FULL test;
VACUUM
[ターミナル2]
postgres=# SELECT * FROM pg_stat_progress_cluster;
(0 rows)

postgres=# 
postgres=# \watch 1
(0 rows)

Fri Jul  5 08:32:26 2019 (every 1s)

-[ RECORD 1 ]-------+------------------
pid                 | 80
datid               | 12674
datname             | postgres
relid               | 16400
command             | VACUUM FULL
phase               | seq scanning heap
cluster_index_relid | 0
heap_tuples_scanned | 778526
heap_tuples_written | 778526
heap_blks_total     | 19912
heap_blks_scanned   | 6890
index_rebuild_count | 0

Fri Jul  5 08:32:27 2019 (every 1s)

-[ RECORD 1 ]-------+------------------
pid                 | 80
datid               | 12674
datname             | postgres
relid               | 16400
command             | VACUUM FULL
phase               | seq scanning heap
cluster_index_relid | 0
heap_tuples_scanned | 2278984
heap_tuples_written | 2278984
heap_blks_total     | 19912
heap_blks_scanned   | 16722
index_rebuild_count | 0

Fri Jul  5 08:32:28 2019 (every 1s)

-[ RECORD 1 ]-------+------------------
pid                 | 80
datid               | 12674
datname             | postgres
relid               | 16400
command             | VACUUM FULL
phase               | seq scanning heap
cluster_index_relid | 0
heap_tuples_scanned | 3000000
heap_tuples_written | 3000000
heap_blks_total     | 19912
heap_blks_scanned   | 19912
index_rebuild_count | 0

(0 rows)

(0 rows)

すると、上記の様に VACUUM FULL の進捗情報を確認することができました。

また、command 列に “VACUUM FULL” と出力されていることから、実行されている処理が VACUUM FULL であることが確認できます。(次に実施する CLUSTER 文では、この command 列に “CLUSTER” と出力されます)

最後に、CLUSTER 文の進捗情報を pg_stat_progress_cluster で確認してみます。

VACUUM FULL の検証と同じ様に、”SELECT * FROM pg_stat_progress_cluster” をループ実行しつつ、別のターミナルで CLUSTER 文を実行してみます。

[ターミナル1]
postgres=# CLUSTER test USING test_a_idx;
CLUSTER
[ターミナル2]
postgres=# SELECT * FROM pg_stat_progress_cluster;
(0 rows)

postgres=# 
postgres=# \watch 1
(0 rows)

Fri Jul  5 08:58:29 2019 (every 1s)

-[ RECORD 1 ]-------+--------------------
pid                 | 80
datid               | 12674
datname             | postgres
relid               | 16400
command             | CLUSTER
phase               | index scanning heap
cluster_index_relid | 16403
heap_tuples_scanned | 843884
heap_tuples_written | 843884
heap_blks_total     | 0
heap_blks_scanned   | 0
index_rebuild_count | 0

Fri Jul  5 08:58:30 2019 (every 1s)

-[ RECORD 1 ]-------+--------------------
pid                 | 80
datid               | 12674
datname             | postgres
relid               | 16400
command             | CLUSTER
phase               | index scanning heap
cluster_index_relid | 16403
heap_tuples_scanned | 2117004
heap_tuples_written | 2117004
heap_blks_total     | 0
heap_blks_scanned   | 0
index_rebuild_count | 0

Fri Jul  5 08:58:31 2019 (every 1s)

-[ RECORD 1 ]-------+--------------------
pid                 | 80
datid               | 12674
datname             | postgres
relid               | 16400
command             | CLUSTER
phase               | index scanning heap
cluster_index_relid | 16403
heap_tuples_scanned | 3000000
heap_tuples_written | 3000000
heap_blks_total     | 0
heap_blks_scanned   | 0
index_rebuild_count | 0

Fri Jul  5 08:58:32 2019 (every 1s)

-[ RECORD 1 ]-------+--------------------
pid                 | 80
datid               | 12674
datname             | postgres
relid               | 16400
command             | CLUSTER
phase               | index scanning heap
cluster_index_relid | 16403
heap_tuples_scanned | 3000000
heap_tuples_written | 3000000
heap_blks_total     | 0
heap_blks_scanned   | 0
index_rebuild_count | 0

(0 rows)

すると、上記の様に CLUSTER の進捗情報を確認することができました。

また、先ほどの VACUUM FULL の場合と異なり command 列に “CLUSTER” と出力されていることから、実行されている処理が CLUSTER であることが確認できます。

■最後に

今回は PostgreSQL 12 で実装予定の pg_stat_progress_create_index 及び pg_stat_progress_cluster について検証してみました。

CREATE INDEX, VACUUM FULL, CLUSTER は、それなりの負荷が発生することや競合する範囲が広めのロックが取得されることから、(特に運用中の DB では) 実行に慎重になるケースが多く、そのような状況で処理に時間を要していると、なかなかプロンプトが返ってこずに不安になることもあると思います。

そのような場合でも、今回検証した pg_stat_progress_create_index や pg_stat_progress_cluster を利用すれば、それらの処理の進捗状況を確認することができるので、DB の運用をされている方々には嬉しい新機能なのではないかと思います。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です