Résolution des problèmes de performance de vacuum dans RDS pour PostgreSQL - Amazon Relational Database Service

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Résolution des problèmes de performance de vacuum dans RDS pour PostgreSQL

Cette section décrit les facteurs qui contribuent souvent au ralentissement des performances de vacuum et explique comment résoudre ces problèmes.

Vacuum des index de grande taille

VACUUM fonctionne selon des phases séquentielles : initialisation, analyse des tas, vacuum des index et des tas, nettoyage des index, troncature des tas et nettoyage final. Pendant l’analyse des tas, le processus élague les pages, les défragmente et les gèle. Une fois l’analyse des tas terminée, VACUUM nettoie les index, renvoie les pages vides au système d’exploitation et effectue les dernières tâches de nettoyage, telles que le vacuum de la carte de l’espace libre et la mise à jour des statistiques.

L’opération de vacuum de l’index peut nécessiter plusieurs passages lorsque la capacité maintenance_work_mem (ou autovacuum_work_mem) est insuffisante pour traiter l’index. Dans PostgreSQL 16 et versions antérieures, une limite de mémoire de 1 Go pour le stockage des ID de tuple inactifs imposait souvent plusieurs passages sur les index volumineux. PostgreSQL 17 introduit TidStore, qui alloue de la mémoire de manière dynamique au lieu d’utiliser un tableau à allocation unique. Cela permet de supprimer la contrainte de 1 Go, d’utiliser la mémoire de manière plus efficace et d’éviter d’avoir à analyser plusieurs fois chaque index.

Les index de grande taille peuvent toujours nécessiter plusieurs passages dans PostgreSQL 17 si la mémoire disponible ne peut pas prendre en charge l’intégralité du traitement des index en une seule fois. Généralement, les index de grande taille contiennent davantage de tuples inactifs qui nécessitent plusieurs passages.

Détection des opérations de vacuum lentes

La fonction postgres_get_av_diag() peut détecter les opérations de vacuum qui sont lentes en raison d’une mémoire insuffisante. Pour plus d’informations sur cette fonction, consultez Installation d’outils de surveillance et de diagnostic d’autovacuum dans RDS pour PostgreSQL.

La fonction postgres_get_av_diag() émet les notifications suivantes lorsque la mémoire disponible n’est pas suffisante pour terminer l’opération de vacuum de l’index en un seul passage.

rds_tools 1.8

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
NOTICE: The current setting of autovacuum_work_mem is "XXX" and might not be sufficient. Consider increasing the setting, and if necessary, scaling up the Amazon RDS instance class for more memory. 
        Additionally, review the possibility of manual vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;).

rds_tools 1.9

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
NOTICE: The current setting of autovacuum_work_mem is XX might not be sufficient. Consider increasing the setting to XXX, and if necessary, scaling up the RDS instance class for more 
        memory. The suggested value is an estimate based on the current number of dead tuples for the table being vacuumed, which might not fully reflect the latest state. Additionally, review the possibility of manual 
        vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;). For more information, see 
        Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide
        .
Note

La fonction postgres_get_av_diag() repose sur pg_stat_all_tables.n_dead_tup pour l’estimation de la quantité de mémoire requise pour l’opération de vacuum de l’index.

Lorsque la fonction postgres_get_av_diag() identifie une opération de vacuum lente qui nécessite plusieurs analyses d’index en raison d’une capacité autovacuum_work_mem insuffisante, elle génère le message suivant :

NOTICE: Your vacuum is performing multiple index scans due to insufficient autovacuum_work_mem:XXX for index vacuuming. 
        For more information, see Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide.

Conseils

Vous pouvez appliquer les solutions de contournement suivantes à l’aide d’une opération VACUUM FREEZE manuelle pour accélérer le gel de la table.

Augmentation de la mémoire pour l’opération de vacuum

Comme suggéré par la fonction postgres_get_av_diag(), il est conseillé d’augmenter le paramètre autovacuum_work_mem pour faire face aux contraintes de mémoire potentielles au niveau de l’instance. Même si autovacuum_work_mem est un paramètre dynamique, il est important de noter que pour que le nouveau paramètre de mémoire prenne effet, le démon autovacuum doit redémarrer ses applications de travail. Pour ce faire :

  1. Vérifiez que le nouveau paramètre est en place.

  2. Arrêtez les processus qui exécutent une opération d’autovacuum.

Cette approche garantit que l’allocation de mémoire ajustée est appliquée aux nouvelles opérations d’autovacuum.

Pour des résultats plus immédiats, pensez à effectuer une opération VACUUM FREEZE manuelle avec un paramètre maintenance_work_mem augmenté au cours de votre session :

SET maintenance_work_mem TO '1GB'; VACUUM FREEZE VERBOSE table_name;

Si vous utilisez Amazon RDS et que vous constatez que vous avez besoin de mémoire supplémentaire pour prendre en charge des valeurs plus élevées pour maintenance_work_mem ou autovacuum_work_mem, envisagez de passer à une classe d’instance avec plus de mémoire. Cela peut fournir les ressources nécessaires pour améliorer les opérations de vacuum manuelles et automatiques, ce qui se traduit par une amélioration des performances globales du vacuum et des bases de données.

Désactivation d’INDEX_CLEANUP

L’opération VACUUM manuelle de PostgreSQL 12 et versions ultérieures permet d’ignorer la phase de nettoyage de l’index, tandis que l’autovacuum d’urgence dans PostgreSQL 14 et versions ultérieures le fait automatiquement en fonction du paramètre vacuum_failsafe_age.

Avertissement

Ignorer le nettoyage de l’index peut entraîner un gonflement de l’index et avoir un impact négatif sur les performances des requêtes. Pour pallier ce problème, pensez à réindexer les index concernés ou à en effectuer le vacuum pendant une période de maintenance.

Pour obtenir des conseils supplémentaires sur la gestion des index de grande taille, reportez-vous à la documentation sur Gestion de la fonction autovacuum avec de grands index .

Opérations de vacuum d’index en parallèle

À partir de PostgreSQL 13, les index peuvent faire l’objet d’un vacuum et d’un nettoyage en parallèle par défaut avec une opération VACUUM manuelle. Un processus de travail de vacuum est alors assigné à chaque index. Cependant, pour que PostgreSQL puisse déterminer si une opération de vacuum peut être exécutée en parallèle, des critères spécifiques doivent être remplis :

  • Il doit y avoir au moins deux index.

  • Le paramètre max_parallel_maintenance_workers doit être défini sur au moins 2.

  • La taille de l’index doit dépasser la limite de min_parallel_index_scan_size, qui est par défaut de 512 Ko.

Vous pouvez ajuster le paramètre max_parallel_maintenance_workers en fonction du nombre de processeurs virtuels disponibles sur votre instance Amazon RDS et du nombre d’index sur la table afin d’optimiser le délai d’exécution de l’opération de vacuum.

Pour plus d’informations, consultez Opérations de vacuum en parallèle dans Amazon RDS pour PostgreSQL et Amazon Aurora PostgreSQL.

Trop de tables ou de bases de données pour le vacuum

Comme indiqué dans la documentation The Autovacuum Daemon de PostgreSQL, le démon autovacuum fonctionne par le biais de plusieurs processus. Cela inclut un lanceur d’autovacuum permanent chargé de démarrer les processus de travail d’autovacuum pour chaque base de données du système. Le lanceur programme ces applications de travail pour qu’elles soient lancées environ toutes les autovacuum_naptime secondes par base de données.

Avec « N » bases de données, une nouvelle application de travail commence environ toutes les [autovacuum_naptime/N secondes]. Cependant, le nombre total d’applications de travail simultanés est limité par le paramètre autovacuum_max_workers. Si le nombre de bases de données ou de tables qui nécessitent un vacuum dépasse cette limite, la base de données ou table suivante est traitée dès qu’une application de travail est disponible.

Lorsque de nombreuses tables ou bases de données volumineuses nécessitent un vacuum simultané, toutes les applications de travail d’autovacuum disponibles peuvent être occupées pendant une période prolongée, ce qui retarde la maintenance des autres tables et bases de données. Dans les environnements où les taux de transactions sont élevés, ce goulot d’étranglement peut rapidement s’aggraver et potentiellement entraîner des problèmes de vacuum de bouclage au sein de votre instance Amazon RDS.

Lorsque postgres_get_av_diag() détecte un nombre élevé de tables ou de bases de données, il fournit la recommandation suivante :

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
NOTICE: The current setting of autovacuum_max_workers:3 might not be sufficient. Consider increasing the setting and, if necessary, consider scaling up the Amazon RDS instance class for more workers.

Conseils

Augmentation d’autovacuum_max_workers

Pour accélérer l’opération de vacuum, nous vous recommandons de régler le paramètre autovacuum_max_workers afin d’autoriser un plus grand nombre d’applications de travail d’autovacuum simultanées. Si les problèmes de performances persistent, envisagez d’augmenter verticalement votre instance Amazon RDS vers une classe comportant davantage de processeurs virtuels, ce qui peut améliorer encore les capacités de traitement parallèle.

Un vacuum agressif (pour éviter tout bouclage) est en cours d’exécution

L’âge de la base de données (MaximumUsedTransactionIDs) dans PostgreSQL ne diminue que lorsqu’un vacuum agressif (pour empêcher tout bouclage) s’est terminé avec succès. Jusqu’à ce que ce vacuum se termine, l’âge continue d’augmenter en fonction du taux de transaction.

La fonction postgres_get_av_diag() génère le message NOTICE suivant lorsqu’elle détecte un vacuum agressif. Cependant, elle ne déclenche cette sortie qu’après que le vacuum a été actif pendant au moins deux minutes.

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.

Pour plus d’informations sur le vacuum agressif, consultez Lorsqu’un vacuum agressif est déjà en cours d’exécution.

Vous pouvez vérifier si un vacuum agressif est en cours à l’aide de la requête suivante :

SELECT a.xact_start AS start_time, v.datname "database", a.query, a.wait_event, v.pid, v.phase, v.relid::regclass, pg_size_pretty(pg_relation_size(v.relid)) AS heap_size, ( SELECT string_agg(pg_size_pretty(pg_relation_size(i.indexrelid)) || ':' || i.indexrelid::regclass || chr(10), ', ') FROM pg_index i WHERE i.indrelid = v.relid ) AS index_sizes, trunc(v.heap_blks_scanned * 100 / NULLIF(v.heap_blks_total, 0)) AS step1_scan_pct, v.index_vacuum_count || '/' || ( SELECT count(*) FROM pg_index i WHERE i.indrelid = v.relid ) AS step2_vacuum_indexes, trunc(v.heap_blks_vacuumed * 100 / NULLIF(v.heap_blks_total, 0)) AS step3_vacuum_pct, age(CURRENT_TIMESTAMP, a.xact_start) AS total_time_spent_sofar FROM pg_stat_activity a INNER JOIN pg_stat_progress_vacuum v ON v.pid = a.pid;

Vous pouvez déterminer s’il s’agit d’un vacuum agressif (pour éviter tout bouclage) en vérifiant la colonne de requête dans la sortie. L’expression « pour éviter tout bouclage » indique qu’il s’agit d’un vacuum agressif.

query | autovacuum: VACUUM public.t3 (to prevent wraparound)

Supposons, par exemple, que vous disposiez d’un bloqueur à l’âge d’un milliard de transactions et d’une table nécessitant un vacuum agressif pour éviter tout bouclage au même âge de transaction. De plus, il existe un autre bloqueur à l’âge de 750 millions de transactions. Après avoir éliminé le bloqueur à l’âge d’un milliard de transactions, l’âge des transactions ne tombera pas immédiatement à 750 millions. Il restera élevé jusqu’à ce que la table nécessitant un vacuum agressif ou toute transaction dont l’âge est supérieur à 750 millions soit finalisée. Au cours de cette période, l’âge des transactions de votre cluster PostgreSQL continuera d’augmenter. Une fois le processus de vacuum terminé, l’âge des transactions tombe à 750 millions, mais recommence à augmenter jusqu’à ce que l’opération de vacuum soit terminée. Ce cycle se poursuit tant que ces conditions persistent, jusqu’à ce que l’âge des transactions atteigne finalement le niveau configuré pour votre instance Amazon RDS, spécifié par autovacuum_freeze_max_age.