こんにちは。サイオステクノロジー 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 の運用をされている方々には嬉しい新機能なのではないかと思います。