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 une nextval
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 session SELECT 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 la pgstattuple
fonction.
Démo avec 9.1: créer une table vide
CREATE TABLE tt AS (n numeric);
Insérons 10 millions de lignes dedans:
INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);
Dans une autre session, vérifiez pgstattuple toutes les secondes lors de l'insertion:
$ while true;
do psql -Atc "select dead_tuple_count from pgstattuple('tt')";
sleep 1;
done
Résultats:
0
69005
520035
1013430
1492210
1990415
2224625
2772040
3314460
3928660
4317345
4743770
5379430
6080950
6522915
7190395
7953705
8747725
9242045
0
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
ou SELECT * INTO newtable
), car la création est effectuée en transaction. La solution de contournement serait de créer la table sans lignes (add LIMIT 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:
/* transformation */
INSERT INTO destination_table
SELECT (r).*
FROM (SELECT counter(to_destination_table(_source), 1000, true) r
FROM source _source) x
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 .
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!