In PostgreSQL, molti comandi DDL possono richiedere molto tempo per essere eseguiti. PostgreSQL ha la capacità di segnalare lo stato di avanzamento dei comandi DDL durante l'esecuzione dei comandi. Da PostgreSQL 9.6, è stato possibile monitorare l'andamento dell'esecuzione di VACUUM manuale e autovacuum utilizzando un catalogo di sistema dedicato (chiamato pg_stat_progress_vacuum).
PostgreSQL 12 ha aggiunto il supporto per il monitoraggio dell'avanzamento di alcuni altri comandi come CLUSTER, VACUUM FULL, CREATE INDEX e REINDEX.
Attualmente, la funzione di reporting sull'avanzamento è disponibile solo per il comando come di seguito.
- comando VACUUM
- comando CLUSTER
- comando VUOTO PIENO
- comando CREA INDICE
- comando REINDEX
Perché la funzione di report sui progressi in PostgreSQL è importante?
Questa funzione è molto importante per gli operatori quando eseguono operazioni di lunga durata, poiché è possibile non attendere alla cieca che un'operazione finisca.
Questa è una funzione molto utile per ottenere informazioni come:
- Quanto lavoro totale c'è
- Quanto lavoro già svolto
La funzione di report sui progressi è utile anche quando si esegue l'analisi del carico di lavoro delle prestazioni, questo si sta rivelando utile anche per valutare l'elaborazione del lavoro VACUUM per ottimizzare i parametri a livello di sistema o il livello di relazione una volta a seconda del modello di carico.
Comandi supportati e catalogo di sistema
Comando DDL | Catalogo di sistema | Versione PostgreSQL supportata |
VUOTO | pg_stat_progress_vacuum | 9.6 |
VUOTO PIENO | pg_stat_progress_cluster | 12 |
CLUSTER | pg_stat_progress_cluster | 12 |
CREA INDICE | pg_stat_progress_create_index | 12 |
REINDEX | pg_stat_progress_create_index | 12 |
Come monitorare l'andamento del comando VACUUM
Ogni volta che il comando VACUUM è in esecuzione, la vista pg_stat_progress_vacuum conterrà una riga per ogni back-end (inclusi i processi di lavoro di autovacuum) che sta attualmente aspirando. La visualizzazione per controllare lo stato di avanzamento dei comandi VACUUM e VACUUM FULL è diversa perché le fasi di funzionamento di entrambi i comandi sono diverse.
Fasi Operative del Comando VACUUM
- Inizializzazione
- Scansione heap
- Indici di aspirazione
- Heap di aspirazione
- Pulizia degli indici
- Heap di troncamento
- Esecuzione della pulizia finale
Questa vista è disponibile in PostgreSQL 12 che fornisce le seguenti informazioni:
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 | | |
Esempio:
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
Sessione 1:
postgres=# vacuum verbose test;
[. . . waits for completion . . .]
Sessione 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
Report sullo stato di avanzamento per CLUSTER e VACUUM FULL
I comandi CLUSTER e VACUUM FULL utilizzano gli stessi percorsi di codice per la riscrittura della relazione, quindi puoi controllare l'avanzamento di entrambi i comandi utilizzando la vista pg_stat_progress_cluster.
Questa vista è disponibile in PostgreSQL 12 e mostra le seguenti informazioni:
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 | | |
Fasi operative del comando CLUSTER
- Inizializzazione
- Heap di scansione sequenziale
- Heap di scansione dell'indice
- Ordinamento delle tuple
- Scrittura di un nuovo heap
- Scambio di file di relazione
- Ricostruire l'indice
- Esecuzione della pulizia finale
Esempio:
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.
Sessione 1:
postgres=# cluster verbose test using idx1;
[. . . waits for completion . . .]
Sessione 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)
Rapporti sull'andamento di CREATE INDEX e REINDEX
Ogni volta che viene eseguito il comando CREATE INDEX o REINDEX, la vista pg_stat_progress_create_index conterrà una riga per ogni backend che sta creando gli indici. La funzione di report sullo stato di avanzamento consente di tenere traccia anche delle versioni CONCURRENTLY di CREATE INDEX e REINDEX. Le fasi interne di esecuzione dei comandi CREATE INDEX e REINDEX sono le stesse, quindi puoi controllare lo stato di avanzamento di entrambi i comandi utilizzando la stessa vista.
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 | | |
Fasi operative di CREATE INDEX / REINDEX
- Inizializzazione
- Aspettando gli autori prima di creare
- Indice edificio
- In attesa degli autori prima della convalida
- Convalida dell'indice:scansione dell'indice
- Convalida dell'indice: ordinamento delle tuple
- Convalida dell'indice:tabella di scansione
- In attesa di vecchie istantanee
- Aspettando i lettori prima di contrassegnare come morto
- Attendere i lettori prima di abbandonare
Esempio:
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
Sessione 1:
postgres=# CREATE INDEX idx ON test (b);
[. . . waits for completion . . .]
Sessione 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
Conclusione
PostgreSQL dalla versione 9.6 in poi ha la capacità di segnalare lo stato di avanzamento di determinati comandi durante l'esecuzione dei comandi. Questa è una funzionalità davvero interessante per DBA, sviluppatori e utenti per controllare l'avanzamento dei comandi di lunga durata. Questa capacità di segnalazione potrebbe estendersi ad altri comandi in futuro. Puoi leggere di più su questa nuova funzionalità nella documentazione di PostgreSQL.