No PostgreSQL, muitos comandos DDL podem levar muito tempo para serem executados. O PostgreSQL tem a capacidade de relatar o progresso dos comandos DDL durante a execução do comando. Desde o PostgreSQL 9.6, é possível monitorar o progresso da execução manual de VACUUM e autovacuum usando um catálogo de sistema dedicado (chamado pg_stat_progress_vacuum).
O PostgreSQL 12 adicionou suporte para monitorar o progresso de mais alguns comandos como CLUSTER, VACUUM FULL, CREATE INDEX e REINDEX.
Atualmente, o recurso de relatório de progresso está disponível apenas para comandos conforme abaixo.
- comando VACUUM
- comando CLUSTER
- comando VACUUM FULL
- comando CRIAR ÍNDICE
- Comando REINDEX
Por que o recurso de relatório de progresso no PostgreSQL é importante?
Esse recurso é muito importante para os operadores ao realizar algumas operações de longa duração, pois é possível não esperar cegamente pela conclusão de uma operação.
Este é um recurso muito útil para obter alguns insights como:
- Quanto trabalho total existe
- Quanto trabalho já foi feito
Recurso de relatório de progresso também é útil ao fazer análise de carga de trabalho de desempenho, isso também está provando ser útil na avaliação de processamento de trabalho VACUUM para ajustar parâmetros de nível de sistema ou nível de relação uma vez, dependendo do padrão de carga.
Comandos suportados e catálogo do sistema
Comando DDL | Catálogo do Sistema | Versão suportada do PostgreSQL |
VACUUM | pg_stat_progress_vacuum | 9,6 |
VACUUM FULL | pg_stat_progress_cluster | 12 |
CLUSTER | pg_stat_progress_cluster | 12 |
CRIAR ÍNDICE | pg_stat_progress_create_index | 12 |
REINDEX | pg_stat_progress_create_index | 12 |
Como monitorar o progresso do comando VACUUM
Sempre que o comando VACUUM estiver em execução, a visualização pg_stat_progress_vacuum conterá uma linha para cada back-end (incluindo processos de trabalho de autovacuum) que está limpando no momento. A visualização para verificar o progresso da execução dos comandos VACUUM e VACCUM FULL é diferente porque as fases de operação de ambos os comandos são diferentes.
Fases de operação do comando VACUUM
- Inicializando
- Pilha de digitalização
- Aspirando índices
- Aspirando pilha
- Limpando índices
- Truncar heap
- Realizando a limpeza final
Esta visualização está disponível no PostgreSQL 12, que fornece as seguintes informações:
postgres=# \d pg_stat_progress_vacuum ;
View "pg_catalog.pg_stat_progress_vacuum"
Column | Type | Collation | Nullable | Default
--------------------+---------+-----------+----------+---------
pid | integer | | |
datid | oid | | |
datname | name | | |
relid | oid | | |
phase | text | | |
heap_blks_total | bigint | | |
heap_blks_scanned | bigint | | |
heap_blks_vacuumed | bigint | | |
index_vacuum_count | bigint | | |
max_dead_tuples | bigint | | |
num_dead_tuples | bigint | | |
Exemplo:
postgres=# create table test ( a int, b varchar(40), c timestamp );
CREATE TABLE
postgres=# insert into test ( a, b, c ) select aa, bb, cc from generate_series(1,10000000) aa, md5(aa::varchar) bb, now() cc;
INSERT 0 10000000
postgres=# DELETE FROM test WHERE mod(a,6) = 0;
DELETE 1666666
Sessão 1:
postgres=# vacuum verbose test;
[. . . waits for completion . . .]
Sessão 2:
postgres=# select * from pg_stat_progress_vacuum;
-[ RECORD 1 ]------+--------------
pid | 22800
datid | 14187
datname | postgres
relid | 16388
phase | scanning heap
heap_blks_total | 93458
heap_blks_scanned | 80068
heap_blks_vacuumed | 80067
index_vacuum_count | 0
max_dead_tuples | 291
num_dead_tuples | 18
Relatório de progresso para CLUSTER e VACUUM FULL
Os comandos CLUSTER e VACUUM FULL usam os mesmos caminhos de código para a reescrita da relação, então você pode verificar o progresso de ambos os comandos usando a visualização pg_stat_progress_cluster.
Esta visualização está disponível no PostgreSQL 12 e mostra as seguintes informações:
postgres=# \d pg_stat_progress_cluster
View "pg_catalog.pg_stat_progress_cluster"
Column | Type | Collation | Nullable | Default
---------------------+---------+-----------+----------+---------
pid | integer | | |
datid | oid | | |
datname | name | | |
relid | oid | | |
command | text | | |
phase | text | | |
cluster_index_relid | bigint | | |
heap_tuples_scanned | bigint | | |
heap_tuples_written | bigint | | |
heap_blks_total | bigint | | |
heap_blks_scanned | bigint | | |
index_rebuild_count | bigint | | |
Fases de operação do comando CLUSTER
- Inicializando
- Heap de varredura sequencial
- Heap de varredura de índice
- Classificando tuplas
- Escrevendo novo heap
- Trocando arquivos de relação
- Reconstruindo índice
- Realizando a limpeza final
Exemplo:
postgres=# create table test as select a,md5(a::text) as txt, now() as date from generate_series(1,3000000) a;
SELECT 3000000
postgres=# create index idx1 on test(a);
CREATE INDEX
postgres=# create index idx2 on test(txt);
CREATE INDEX
postgres=# create index idx3 on test(date);
CREATE INDEX
Now execute the CLUSTER table command and see the progress in pg_stat_progress_cluster.
Sessão 1:
postgres=# cluster verbose test using idx1;
[. . . waits for completion . . .]
Sessão 2:
postgres=# select * from pg_stat_progress_cluster;
pid | datid | datname | relid | command | phase | cluster_index_relid | heap_tuples_scanned | heap_tuples_written | heap_blks_total | heap_blks_scanned | index_rebuild_count
------+-------+----------+-------+---------+------------------+---------------------+---------------------+---------------------+-----------------+-------------------+---------------------
1273 | 13586 | postgres | 15672 | CLUSTER | rebuilding index | 15680 | 3000000 | 3000000 | 0 | 0 | 2
(1 row)
Relatório de progresso para CREATE INDEX e REINDEX
Sempre que o comando CREATE INDEX ou REINDEX estiver em execução, a visualização pg_stat_progress_create_index conterá uma linha para cada backend que está criando índices no momento. O recurso de relatório de progresso permite rastrear também os sabores CONCORRENTEMENTE de CREATE INDEX e REINDEX. As fases internas de execução dos comandos CREATE INDEX e REINDEX são as mesmas, portanto, você pode verificar o andamento de ambos os comandos usando a mesma visualização.
postgres=# \d pg_stat_progress_create_index
View "pg_catalog.pg_stat_progress_create_index"
Column | Type | Collation | Nullable | Default
--------------------+---------+-----------+----------+---------
pid | integer | | |
datid | oid | | |
datname | name | | |
relid | oid | | |
phase | text | | |
lockers_total | bigint | | |
lockers_done | bigint | | |
current_locker_pid | bigint | | |
blocks_total | bigint | | |
blocks_done | bigint | | |
tuples_total | bigint | | |
tuples_done | bigint | | |
partitions_total | bigint | | |
partitions_done | bigint | | |
Fases de operação de CREATE INDEX / REINDEX
- Inicializando
- Aguardando escritores antes de construir
- Construindo índice
- Aguardando redatores antes da validação
- Validação de índice:verificação de índice
- Validação de índice: classificação de tuplas
- Validação de índice:tabela de varredura
- Aguardando instantâneos antigos
- Aguardando os leitores antes de marcar como morto
- Aguardando os leitores antes de sair
Exemplo:
postgres=# create table test ( a int, b varchar(40), c timestamp );
CREATE TABLE
postgres=# insert into test ( a, b, c ) select aa, bb, cc from generate_series(1,10000000) aa, md5(aa::varchar) bb, now() cc;
INSERT 0 10000000
postgres=# CREATE INDEX idx ON test (b);
CREATE INDEX
Sessão 1:
postgres=# CREATE INDEX idx ON test (b);
[. . . waits for completion . . .]
Sessão 2:
postgres=# SELECT * FROM pg_stat_progress_create_index;
-[ RECORD 1 ]------+-------------------------------
pid | 19432
datid | 14187
datname | postgres
relid | 16405
index_relid | 0
command | CREATE INDEX
phase | building index: scanning table
lockers_total | 0
lockers_done | 0
current_locker_pid | 0
blocks_total | 93458
blocks_done | 46047
tuples_total | 0
tuples_done | 0
partitions_total | 0
partitions_done | 0
postgres=# SELECT * FROM pg_stat_progress_create_index;
-[ RECORD 1 ]------+---------------------------------------
pid | 19432
datid | 14187
datname | postgres
relid | 16405
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 | 10000000
tuples_done | 4346240
partitions_total | 0
partitions_done | 0
Conclusão
O PostgreSQL versão 9.6 em diante tem a capacidade de relatar o progresso de certos comandos durante a execução do comando. Este é um recurso muito bom para DBAs, desenvolvedores e usuários verificarem o progresso de comandos de longa execução. Esse recurso de relatório pode se estender para alguns outros comandos no futuro. Você pode ler mais sobre esse novo recurso na documentação do PostgreSQL.