Non sembra esserci un metodo generico supportato, ma ci sono alcuni trucchi che possono essere utilizzati in contesti limitati per valutare lo stato di avanzamento di una singola query. Qui ce ne sono un po.
sequenze
Quando una query SELECT o UPDATE ne include una nextval(sequence_name)
o un INSERT ha una colonna di destinazione con un nextval
valore predefinito, il valore della sequenza corrente può essere ripetutamente interrogato in un'altra sessione con SELECT sequence_name.last_value
. Funziona perché le sequenze non sono limitate dalle transazioni. Quando il piano di esecuzione è tale che la sequenza viene incrementata linearmente durante la query, può essere utilizzata come indicatore di avanzamento.
pgstattuple
Il modulo contrib di pgstattuple fornisce funzioni che possono sbirciare direttamente le pagine dei dati. Sembra che quando le tuple vengono inserite in una tabella vuota e non ancora impegnate, vengono contate nel dead_tuple_count
campo dalla pgstattuple
funzione.
Demo con 9.1: crea una tabella vuota
CREATE TABLE tt AS (n numeric);
Inseriamo 10 M righe al suo interno:
INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);
In un'altra sessione, controlla pgstattuple ogni secondo durante l'inserimento:
$ while true;
do psql -Atc "select dead_tuple_count from pgstattuple('tt')";
sleep 1;
done
risultati:
0
69005
520035
1013430
1492210
1990415
2224625
2772040
3314460
3928660
4317345
4743770
5379430
6080950
6522915
7190395
7953705
8747725
9242045
0
Ritorna a 0 al termine dell'inserto (tutte le tuple diventano visibili e attive).
Questo trucco può essere utilizzato anche quando la tabella non è stata creata di recente, ma dead_tuple_count
è probabile che l'iniziale abbia un valore diverso da zero e può anche cambiare contemporaneamente se altre attività di scrittura come l'autovacuum sono in corso (presumibilmente? Non sei sicuro di quale livello di concorrenza da aspettarsi con autovacuum).
Tuttavia, non può essere utilizzato se la tabella viene creata dall'istruzione stessa ( CREATE TABLE ... AS SELECT
o SELECT * INTO newtable
), poiché la creazione viene eseguita. La soluzione alternativa sarebbe quella di creare la tabella senza righe (aggiungere LIMIT 0
) e compilarla nella transazione successiva.
Nota che pgstattuple
non è gratuito: scansiona l'intero tavolo ad ogni chiamata. Inoltre è limitato ai super utenti.
Contatore personalizzato
Nel blog di Pavel Stehule, fornisce una funzione contatore implementata in C che genera AVVISI a un numero specificato di esecuzioni. Devi combinare la funzione con la query in qualche modo per consentire all'esecutore di chiamarla. Gli avvisi vengono inviati durante la query e non necessitano di una sessione separata, ma solo di un client SQL che li visualizza ( psql
essendo il candidato ovvio).
Esempio di INSERT INTO rielaborato per generare avvisi:
/* transformation */
INSERT INTO destination_table
SELECT (r).*
FROM (SELECT counter(to_destination_table(_source), 1000, true) r
FROM source _source) x
Domanda correlata su StackOverflow, per funzioni:
come segnalare i progressi dalla funzione PostgreSQL a esecuzione prolungata al client
Opzioni future?
A partire da maggio 2017, c'è una promettente patch inviata alla comunità degli sviluppatori:
[PATCH v2] Comando progress per monitorare la progressione di query SQL a esecuzione prolungata
che potrebbe finire come una soluzione generica in PostgreSQL 11 o versioni successive. Gli utenti che desiderano partecipare alle funzionalità work-in-progress possono applicare l'ultima versione della patch e provare il PROGRESS
comando proposto .
pv
comando prima, e non era installato sul mio server Debian per impostazione predefinita, ma è nel repository. La descrizione dice "pv (Pipe Viewer) può essere inserito in qualsiasi normale pipeline tra due processi per dare un'indicazione visiva della velocità con cui i dati passano". Un comando molto utile!