Comme l'a mentionné Daniel Vérité, il ne semble pas exister de solution générique. Lors du chargement de données dans une table à partir d'un fichier, la technique suivante peut être utilisée pour obtenir la progression du chargement.
Barre de progression de la console de commande COPY
Créez une table vide.
CREATE TABLE mytest (n int);
Créez un fichier de données avec 10 millions de lignes à charger dans la table.
$ seq 10000000 > /tmp/data.txt
Chargez les données du fichier dans la table et affichez une barre de progression.
$ pv /tmp/data.txt | psql -c "COPY mytest FROM STDIN;"
Démo
Comment ça marche
En utilisant l'option STDIN des commandes de copie, nous pouvons introduire les données pour l'opération de copie à partir d'un autre processus. La commande pv produira un fichier et suivra sa progression en affichant une barre de progression, l'ETA, le temps total écoulé et le taux de transfert des données.
Barre de progression graphique de la commande COPY
En utilisant la même technique générale, nous pourrions afficher une barre de progression dans une application graphique ou une application Web. En utilisant python par exemple, le module psycopg2 vous permet d’appeler la commande copy avec un objet fichier de votre choix. Vous pouvez ensuite suivre la quantité de votre objet fichier qui a été lue et afficher une barre de progression.
pv
commande auparavant, et elle n'était pas installée par défaut sur mon serveur Debian, mais c'est dans le référentiel. La description indique que "pv (Pipe Viewer) peut être inséré dans tout pipeline normal entre deux processus pour donner une indication visuelle de la vitesse à laquelle les données transitent". Une commande très utile!Il ne semble pas exister de méthode générique prise en charge, mais certaines astuces peuvent être utilisées dans des contextes limités pour évaluer la progression d'une requête individuelle. En voici quelques uns.
Des séquences
Lorsqu'une requête SELECT ou UPDATE inclut une requête
nextval(sequence_name)
ou qu'une colonne INSERT possède une colonne de destination avec unenextval
valeur par défaut, la valeur de la séquence actuelle peut être interrogée de manière répétée dans une autre sessionSELECT sequence_name.last_value
. Cela fonctionne parce que les séquences ne sont pas liées par des transactions. Lorsque le plan d'exécution est tel que la séquence est incrémentée de manière linéaire au cours de la requête, il peut être utilisé comme indicateur de progression.pgstattuple
Le module contrib de pgstattuple fournit des fonctions qui permettent d’observer directement les pages de données. Il semble que lorsque les n-uplets sont insérés dans une table vide et non encore validés, ils sont comptés dans le
dead_tuple_count
champ à partir de lapgstattuple
fonction.Démo avec 9.1: créer une table vide
Insérons 10 millions de lignes dedans:
Dans une autre session, vérifiez pgstattuple toutes les secondes lors de l'insertion:
Résultats:
Il retombe à 0 lorsque l'insertion est terminée (tous les n-uplets deviennent visibles et vivants).
Cette astuce peut également être utilisée lorsque la table n'est pas fraîchement créée, mais l'initiale
dead_tuple_count
aura probablement une valeur différente de zéro. Elle peut également changer simultanément si d'autres activités d'écriture telles que autovacuum sont en cours (vraisemblablement? Vous ne savez pas quel niveau de simultanéité à attendre avec autovacuum).Cependant, il ne peut pas être utilisé si la table est créée par la déclaration elle-même (
CREATE TABLE ... AS SELECT
ouSELECT * INTO newtable
), car la création est effectuée en transaction. La solution de contournement serait de créer la table sans lignes (addLIMIT 0
) et de la renseigner dans la transaction suivante.Notez que ce
pgstattuple
n'est pas gratuit: il scanne toute la table à chaque appel. En outre, il est limité aux superutilisateurs.Compteur personnalisé
Dans le blog de Pavel Stehule, il fournit une fonction de compteur implémentée en C qui lève les AVIS à un nombre spécifié d'exécutions. Vous devez combiner la fonction avec la requête pour permettre à l’exécuteur de l’appeler. Les avis sont envoyés pendant la requête et ils n'ont pas besoin d'une session séparée, mais uniquement d'un client SQL qui les affiche (
psql
le candidat évident).Exemple d'insertion dans modifiée pour émettre des avis:
Question connexe sur stackoverflow, pour les fonctions:
Comment signaler la progression d'une fonction PostgreSQL de longue durée au client
Options futures?
Depuis mai 2017, un correctif prometteur a été soumis à la communauté des développeurs: commande [PATCH v2] Progress pour surveiller la progression des requêtes SQL de longue durée.
qui pourrait aboutir à une solution générique dans PostgreSQL 11 ou version ultérieure. Les utilisateurs qui ont envie de participer à des fonctionnalités de travail en cours peuvent appliquer la dernière version du correctif et essayer la
PROGRESS
commande proposée .la source
Jusqu'à ce que la fonctionnalité de rapport d'avancement ne soit pas étendue, comme l'a mentionné @AmirAliAkbari dans sa réponse, voici une solution de contournement au niveau du système d'exploitation.
Cela ne fonctionne que sur les Linux, mais il existe probablement des solutions similaires facilement compatibles avec tous les systèmes d'exploitation.
Le plus grand avantage et aussi inconvénient de PostgreSQL, que tous ses backends sont simples processus mono-thread, en utilisant
lseek()
,read()
etwrite()
pour manipuler leurs fichiers de table, alors qu'ils sont en interaction sur mem partagée et les serrures.Cela a pour résultat que tous ses processus backend fonctionnent toujours sur une requête unique, qui peut être facilement trouvée et facilement
strace
d.Tout d’abord, vous pouvez voir le PID principal à partir d’un
SELECT * FROM pg_stat_activity;
:La troisième colonne est le pid. Dans PostgreSQL, il est identique au pid de processus Linux du backend.
Ensuite, vous pouvez le tracer, par exemple avec un
strace -p 20019 -s 8192
: (-s 8192
est utile car postgresql fonctionne avec des blocs longs de 8192 octets).Les significations:
sendto
se passe-t-il si le serveur répond à un client? Dans l'exemple, il répond au résultat d'uneINSERT
requête.recvfrom
se produit si le backend obtient quelque chose d'un client. Il s'agit généralement d'une nouvelle requête, dans l'exemple, encore d'une autreINSERT
.lseek
Cela se produit si le serveur change de position dans un fichier de table.read
se produit si le backend lit un bloc dans un fichier table.write
se passe-t-il si le serveur écrit un bloc dans un fichier table?Dans le cas de
read
etwrite
, vous pouvez également voir le contenu de ce bloc dans la table. Il peut être très utile de comprendre ce qu’il fait et où il se trouve.Dans le cas de
recvfrom
, vous pouvez voir la requête réelle sur le backend.la source
Comme indiqué dans d’autres réponses, il n’existe actuellement aucun moyen direct de faire rapport sur les progrès accomplis.
Cependant, à partir de 9.6,
VACUUM
lapg_stat_progress_vacuum
vue contiendra une ligne pour chaque serveur (y compris les processus de travail autovacuum) à chaque fois qu’elle est en cours d’exécution . Vous trouverez plus de détails sur lapg_stat_progress_vacuum
documentation dans la documentation: 27.4 Rapports d’avancement .la source