Es scheint keine generische, unterstützte Methode zu geben, aber es gibt einige Tricks, die in begrenzten Kontexten verwendet werden können, um den Fortschritt einer einzelnen Abfrage zu bewerten. Hier sind einige davon.
Sequenzen
Wenn eine SELECT- oder UPDATE-Abfrage eine beliebige enthält nextval(sequence_name)
oder ein INSERT eine Zielspalte mit einem nextval
als Standard enthält, kann der aktuelle Sequenzwert in einer anderen Sitzung mit wiederholt abgefragt werden SELECT sequence_name.last_value
. Das funktioniert, weil Sequenzen nicht an Transaktionen gebunden sind. Wenn der Ausführungsplan so ist, dass die Sequenz während der Abfrage linear inkrementiert wird, kann er als Fortschrittsanzeige verwendet werden.
pgstattuple
Das Modul pgstattuple contrib bietet Funktionen, die einen direkten Blick auf die Datenseiten werfen können. Es scheint, dass Tupel, die in eine leere Tabelle eingefügt und noch nicht festgeschrieben wurden, in dem dead_tuple_count
Feld der pgstattuple
Funktion gezählt werden.
Demo mit 9.1: Erstellen Sie eine leere Tabelle
CREATE TABLE tt AS (n numeric);
Fügen wir 10 Millionen Zeilen ein:
INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);
Überprüfen Sie in einer anderen Sitzung pgstattuple jede Sekunde während des Einfügens:
$ while true;
do psql -Atc "select dead_tuple_count from pgstattuple('tt')";
sleep 1;
done
Ergebnisse:
0
69005
520035
1013430
1492210
1990415
2224625
2772040
3314460
3928660
4317345
4743770
5379430
6080950
6522915
7190395
7953705
8747725
9242045
0
Es fällt auf 0 zurück, wenn die Einfügung beendet ist (alle Tupel werden sichtbar und leben).
Dieser Trick kann auch verwendet werden, wenn die Tabelle nicht neu erstellt wurde, die Initiale dead_tuple_count
jedoch wahrscheinlich einen Wert ungleich Null aufweist. Er kann sich auch gleichzeitig ändern, wenn andere Schreibaktivitäten wie z Nebenläufigkeit mit autovacuum zu erwarten).
Es kann jedoch nicht verwendet werden, wenn die Tabelle von der Anweisung selbst ( CREATE TABLE ... AS SELECT
oder SELECT * INTO newtable
) erstellt wird, da die Erstellung transaktioniert wird. Die Problemumgehung besteht darin, die Tabelle ohne Zeilen zu erstellen (Hinzufügen LIMIT 0
) und in der nächsten Transaktion mit Daten zu füllen.
Beachten Sie, dass pgstattuple
dies nicht kostenlos ist: Bei jedem Aufruf wird die gesamte Tabelle durchsucht. Es ist auch auf Superuser beschränkt.
Benutzerdefinierter Zähler
In Pavel Stehules Blog stellt er eine in C implementierte Counter-Funktion bereit, die NOTICEs bei einer festgelegten Anzahl von Ausführungen auslöst. Sie müssen die Funktion irgendwie mit der Abfrage kombinieren, damit der Executor sie aufruft. Benachrichtigungen werden während der Abfrage gesendet und benötigen keine separate Sitzung, sondern nur einen SQL-Client, der sie anzeigt ( psql
der naheliegende Kandidat).
Beispiel für INSERT INTO überarbeitet, um Hinweise zu erhalten:
/* transformation */
INSERT INTO destination_table
SELECT (r).*
FROM (SELECT counter(to_destination_table(_source), 1000, true) r
FROM source _source) x
Verwandte Frage zum Stackoverflow für Funktionen: Wie wird der Fortschritt der PostgreSQL-Funktion mit langer Laufzeit an den Client gemeldet?
Zukünftige Optionen?
Ab Mai 2017 wird der Entwickler-Community ein vielversprechender Patch zur Verfügung gestellt:
[PATCH v2] Progress-Befehl zur Überwachung des Fortschritts lang laufender SQL-Abfragen
Dies könnte eine generische Lösung in PostgreSQL 11 oder höher sein. Benutzer, die an den in Arbeit befindlichen Funktionen teilnehmen möchten, wenden möglicherweise die neueste Version des Patches an und probieren den vorgeschlagenen PROGRESS
Befehl aus.
pv
Befehl gestoßen und er war nicht standardmäßig auf meinem Debian-Server installiert, aber er befindet sich im Repo. In der Beschreibung heißt es: "pv (Pipe Viewer) kann in jede normale Pipeline zwischen zwei Prozessen eingefügt werden, um visuell anzuzeigen, wie schnell Daten übertragen werden." Ein sehr nützlicher Befehl!