Wie Daniel Vérité sagte, scheint es keine generische Lösung zu geben. Beim Laden von Daten aus einer Datei in eine Tabelle kann die folgende Technik verwendet werden, um den Fortschritt des Ladens zu ermitteln.
Fortschrittsanzeige der COPY-Befehlskonsole
Erstellen Sie eine leere Tabelle.
CREATE TABLE mytest (n int);
Erstellen Sie eine Datendatei mit 10 Millionen Zeilen zum Laden in die Tabelle.
$ seq 10000000 > /tmp/data.txt
Laden Sie Daten aus einer Datei in die Tabelle und zeigen Sie einen Fortschrittsbalken an.
$ pv /tmp/data.txt | psql -c "COPY mytest FROM STDIN;"
Demo
Wie das geht
Mit dem Kopierbefehl STDIN können wir die Daten für den Kopiervorgang aus einem anderen Prozess einspeisen. Der Befehl pv gibt eine Datei aus und verfolgt deren Fortschritt. Er zeigt einen Fortschrittsbalken, die ETA, die verstrichene Gesamtzeit und die Datenübertragungsrate an.
Grafische Fortschrittsanzeige für den Befehl KOPIEREN
Mit derselben allgemeinen Technik könnten wir einen Fortschrittsbalken in einer grafischen Anwendung oder einer webbasierten Anwendung anzeigen. Wenn Sie beispielsweise Python verwenden, können Sie mit dem Modul psycopg2 den Befehl copy mit einem Dateiobjekt Ihrer Wahl aufrufen. Sie können dann verfolgen, wie viel von Ihrem Dateiobjekt gelesen wurde, und eine Fortschrittsanzeige anzeigen.
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!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 einemnextval
als Standard enthält, kann der aktuelle Sequenzwert in einer anderen Sitzung mit wiederholt abgefragt werdenSELECT 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 derpgstattuple
Funktion gezählt werden.Demo mit 9.1: Erstellen Sie eine leere Tabelle
Fügen wir 10 Millionen Zeilen ein:
Überprüfen Sie in einer anderen Sitzung pgstattuple jede Sekunde während des Einfügens:
Ergebnisse:
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
oderSELECT * INTO newtable
) erstellt wird, da die Erstellung transaktioniert wird. Die Problemumgehung besteht darin, die Tabelle ohne Zeilen zu erstellen (HinzufügenLIMIT 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:
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.quelle
Bis die Funktionalität des Fortschrittsberichts nicht erweitert wird, wie @AmirAliAkbari in seiner Antwort erwähnt hat, gibt es hier eine Problemumgehung auf Betriebssystemebene.
Dies funktioniert nur unter Linux, aber wahrscheinlich gibt es ähnliche Lösungen für alle Betriebssysteme, die leicht zu finden sind.
Der größte Vorteil und auch Nachteil der PostgreSQL, dass alle seiner Backends einfache Single-Threaded - Prozesse sind, mit
lseek()
,read()
undwrite()
ihre Tabellendateien zu manipulieren, während sie auf gemeinsame mem und Schlössern interagieren.Dies hat zur Folge, dass alle Backend-Prozesse immer an einer einzigen Abfrage arbeiten, die leicht gefunden werden kann, und
strace
d.Zuerst können Sie die Backend-PID von einem sehen
SELECT * FROM pg_stat_activity;
:Die dritte Spalte ist die PID. In PostgreSQL ist es dasselbe wie die Linux-Prozess-PID des Backends.
Als nächstes können Sie es zum Beispiel durch ein
strace -p 20019 -s 8192
: (-s 8192
ist nützlich, weil postgresql mit 8192-Byte-langen Blöcken arbeitet).Die Bedeutungen:
sendto
passiert, wenn das Backend einem Client etwas antwortet. Im Beispiel wird das Ergebnis einerINSERT
Abfrage beantwortet.recvfrom
passiert, wenn das Backend etwas von einem Client bekommt. Es ist in der Regel eine neue Abfrage, im Beispiel noch eine andereINSERT
.lseek
passiert, wenn das Backend in einer Tabellendatei die Position wechselt.read
passiert, wenn das Backend einen Block aus einer Tabellendatei einliest.write
passiert, wenn das Backend einen Block in eine Tabellendatei schreibt.Im Fall von
read
undwrite
können Sie auch den Inhalt dieses Blocks in der Tabelle sehen. Es kann sehr hilfreich sein zu verstehen, was es tut und wo es ist.Im Fall von sehen
recvfrom
Sie die aktuelle Abfrage, was das Backend hat.quelle
Wie bereits in anderen Antworten erwähnt, gibt es derzeit keinen direkten Weg für die allgemeine Fortschrittsberichterstattung.
Ab Version 9.6 enthält
VACUUM
diepg_stat_progress_vacuum
Ansicht jedoch , wann immer sie ausgeführt wird, eine Zeile für jedes Backend (einschließlich Autovacuum-Worker-Prozessen), das gerade gesaugt wird. Weitere Detailspg_stat_progress_vacuum
finden Sie in der Dokumentation: 27.4 Fortschrittsberichte .quelle