Je gère une grande base de données (quelques centaines de concerts) contenant des tables avec différents rôles, certains d'entre eux détenant des millions d'enregistrements. Certaines tables ne reçoivent qu'un grand nombre d'insertions et de suppressions, d'autres quelques insertions et un grand nombre de mises à jour.
La base de données fonctionne sur PostgreSQL 8.4 sur un système Debian 6.0 AMD64 avec 16 gigaoctets de RAM.
La question est parfois le processus de vide automatique sur une table, prend beaucoup de temps (jours) pour terminer. Je veux pouvoir dire approximativement combien de temps une commande de vide particulière prendra, pour pouvoir décider de l'annuler ou non. De plus, s'il y avait un indicateur de progrès pour les opérations de vide postgres, ce serait vraiment utile.
Éditer:
Je ne cherche pas de solution pare-balles. Une simple indication approximative du nombre de tuples morts ou d'octets d'E/S nécessaires suffit pour décider. C'est vraiment ennuyeux de n'avoir aucune idée quand VACUUM
se terminera, que ce soit.
J'ai vu ça pg_catalog.pg_stat_all_tables
a une colonne pour le nombre de tuples morts. Il est donc possible d'avoir une estimation, même si cela signifie qu'il faut ANALYZE
la table avant. D'autre part, autovacuum_vacuum_threshold
et autovacuum_vacuum_scale_factor
seuls les paramètres prouvent que postgres lui-même sait quelque chose sur la quantité de changement sur les tables et le met probablement entre les mains du DBA aussi.
Je ne sais pas quelle requête exécuter, car lorsque j'exécute VACUUM VERBOSE
, Je constate que non seulement les tables, mais aussi les index sur celles-ci sont en cours de traitement.
Sur mon PostgreSQL (8.3) j'utilise cette astuce:
pg_total_relation_size()
- cela inclut les index et la taille de TOAST, qui est ce que VACUUM
traite. Cela me donne une idée du nombre d'octets que le VACUUM
doit lire.VACUUM
sur la table.pid
du processus VACUUM
(dans pg_catalog.pg_stat_activity
).while true; do cat /proc/123/io | grep read_bytes; sleep 60; done
(où 123
est le pid) - cela me montre les octets lus par le processus à partir du disque jusqu'à présent.Cela me donne une idée approximative du nombre d'octets traités (lus) chaque minute par le VACUUM
. Je suppose que le VACUUM
doit lire toute la table (y compris les index et TOAST), dont je connais la taille du disque à l'étape 1.
Je suppose que la table est suffisamment grande pour que la majorité de ses pages doivent être lues à partir du disque (elles ne sont pas présentes dans la mémoire partagée de Postgres), donc le read_bytes
est assez bon pour être utilisé comme compteur de progression.
Chaque fois que je faisais cela, le nombre total d'octets lus par le processus ne dépassait pas 5% de la taille totale de la relation, donc je suppose que cette approche peut être assez bonne pour vous.
C'est très difficile à déterminer. Vous pouvez régler le vide automatique pour être plus agressif ou pour être plus doux. Mais lorsqu'il est réglé sur doux et qu'il est à la traîne et que la charge d'E/S de base est trop élevée, il peut arriver qu'il n'atteigne jamais un état de vide approprié - alors vous voyez le processus en cours d'exécution et en cours d'exécution. De plus, les éditions ultérieures de PostreSQL ont des capacités d'autovacuum bien améliorées, cela seul peut suffire pour passer à l'une d'entre elles (de préférence 9.2 comme la plus récente).
La barre de progression semble une bonne idée, mais j'imagine que ce n'est pas si facile à mettre en œuvre de manière significative. Comme vous avez une charge constante sur vos tables, il est tout à fait possible que la progression recule apparemment (je veux dire que le nombre/pourcentage de lignes mortes augmente au lieu de diminuer) - alors quelle conclusion tirez-vous?
J'ai trouvé cet article et cet article utiles, mais comme d'autres l'ont mentionné, il peut être difficile de calculer la progression globale du vide, car le processus implique quelques opérations distinctes.
J'utilise cette requête pour surveiller la progression de l'analyse de la table de vide, qui semble être la majeure partie du travail:
SELECT heap_blks_scanned/cast(heap_blks_total as numeric)*100 as heap_blks_percent, progress.*, activity.query
FROM pg_stat_progress_vacuum AS progress
INNER JOIN pg_stat_activity AS activity ON activity.pid = progress.pid;
Cependant, cela n'inclura pas l'analyse d'index, qui se produit ensuite, et peut prendre autant de temps, sinon plus, si vous avez une tonne d'index. Malheureusement, je ne trouve aucun moyen de surveiller le balayage/la mise sous vide de l'index.
Dans notre production, l'une des plus grandes tables avait ce journal:
pages: 0 removed, 1801722 remain
tuples: 238912 removed, 42582083 remain, 1396 are dead but not yet removable
buffer usage: 9477565 hits, 3834218 misses, 2220101 dirtied
avg read rate: 2.976 MB/s, avg write rate: 1.723 MB/s
system usage: CPU 68.47s/177.49u sec elapsed 10065.08 sec
C'est de loin la pire consommation de ressources, toutes les autres tables ont pris moins de 2 s.
Pour voir ces types de journaux, vous devez exécuter ceci:
alter system set log_autovacuum_min_duration TO 5;
(pendant 5 ms), rechargez le fichier de configuration.