Arbeiten mit der PostgreSQL-Selbstbereinigung in Amazon RDS for PostgreSQL - Amazon Relational Database Service

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Arbeiten mit der PostgreSQL-Selbstbereinigung in Amazon RDS for PostgreSQL

Wir empfehlen ausdrücklich die Selbstbereinigungsfunktion zu verwenden, um die Integrität Ihrer PostgreSQL-DB-Instance zu wahren. Die Selbstbereinigung automatisiert den Start der Befehle VACUUM und ANALYZE. Sie prüft auf Tabellen mit einer großen Zahl von eingefügten, aktualisierten oder gelöschten Tupeln. Nach dieser Prüfung wird Speicher durch Entfernen von überflüssigen Daten oder Tupeln aus der PostgreSQL-Datenbank freigegeben.

Standardmäßig ist die Selbstbereinigungsfunktion auf den DB-Instances von Amazon RDS for PostgreSQL aktiviert, die Sie mit einer der standardmäßigen PostgreSQL-DB-Parametergruppen erstellen. Dazu zählen default.postgres10, default.postgres11, usw. Alle standardmäßigen PostgreSQL-DB-Parametergruppen haben den Parameter rds.adaptive_autovacuum, der auf 1 festgelegt ist und die Funktion aktiviert. Andere Konfigurationsparameter, die mit der Selbstbereinigungsfunktion verknüpft sind, sind ebenfalls standardmäßig festgelegt. Da diese Standardwerte generisch sind, können Sie davon profitieren, einige der mit der Selbstbereinigungsfunktion verbundenen Parameter für Ihre spezifische Workload zu optimieren.

Im Folgenden finden Sie weitere Informationen zur Selbstbereinigung und wie Sie einige ihrer Parameter auf Ihrer DB-Instance von RDS for PostgreSQL optimieren können. Informationen auf hoher Ebene finden Sie unter Bewährte Methoden für die Arbeit mit PostgreSQL.

Zuweisen von Arbeitsspeicher für die Selbstbereinigung

Einer der wichtigsten Parameter, der sich auf die Leistung der Selbstbereinigung auswirkt, ist der Parameter maintenance_work_mem. Dieser Parameter legt fest, wie viel Arbeitsspeicher Sie der Selbstbereinigung für das Scannen einer Datenbanktabelle und das Speichern aller Zeilen-IDs zuteilen, für die eine Bereinigung ausgeführt werden soll. Wenn Sie den Wert des Parameters maintenance_work_mem zu niedrig einstellen, muss die Tabelle während des Bereinigungsvorgangs möglicherweise mehrmals gescannt werden, um die Bereinigung auszuführen. Solche wiederholten Scans können negative Auswirkungen auf die Leistung haben.

Sie müssen bei der Berechnung des Werts für den Parameter maintenance_work_mem zwei Dinge berücksichtigen:

  • Die Standardeinheit für diesen Parameter ist Kilobyte (KB).

  • Der Parameter maintenance_work_mem funktioniert in Verbindung mit dem Parameter autovacuum_max_workers. Wenn Sie viele kleine Tabellen haben, müssen Sie mehr autovacuum_max_workers und weniger maintenance_work_mem zuteilen. Wenn Sie große Tabellen haben (beispielsweise größer als 100 GB), sollten Sie mehr Arbeitsspeicher und weniger Worker-Prozesse zuteilen. Sie müssen genügend Arbeitsspeicher zuweisen, um den Vorgang für Ihre größte Tabelle erfolgreich ausführen zu können. Jeder autovacuum_max_workers-Parameter kann den von Ihnen zugeteilten Arbeitsspeicher nutzen. Daher muss die Kombination von Worker-Prozessen und Arbeitsspeicher dem gesamten Arbeitsspeicher entsprechen, den Sie zuteilen möchten.

Allgemein ausgedrückt, müssen Sie für große Hosts den Parameter maintenance_work_mem auf einen Wert zwischen einem und zwei Gigabyte (zwischen 1.048.576 und 2.097.152 KB) festlegen. Im Fall extrem großer Hosts sollten Sie den Parameter auf einen Wert zwischen zwei und vier Gigabyte (zwischen 2.097.152 und 4.194.304 KB) festlegen. Der Wert, den Sie für diesen Parameter festlegen, hängt von der Workload ab. Amazon RDS hat den Standardwert für diesen Parameter auf Kilobyte aktualisiert. Er wird wie folgt berechnet.

GREATEST({DBInstanceClassMemory/63963136*1024},65536).

Verringern der Wahrscheinlichkeit von Transaktions-ID-Wraparounds

In einigen Fällen sind Parametergruppen-Einstellungen, die sich auf die Selbstbereinigung beziehen, möglicherweise nicht aggressiv genug, um Transaktions-ID-Wraparounds zu verhindern. Um dieses Problem zu beheben, stellt RDS for PostgreSQL eine Methode bereit, mit der die Selbstbereinigungsparameter automatisch angepasst werden. Adaptive Optimierung der Selbstbereinigungsparameter ist eine Funktion für RDS for PostgreSQL. In der PostgreSQL-Dokumentation finden Sie eine sehr detaillierte Beschreibung von Transaktions-ID-Wraparounds.

Die adaptive Optimierung von Selbstbereinigungsparametern ist für Instances von RDS for PostgreSQL, bei denen der Parameter rds.adaptive_autovacuum auf ON gesetzt ist, automatisch aktiviert. Wir raten dringend dazu, diese Option aktiviert zu lassen. Um die adaptive Optimierung der Selbstbereinigungsparameter zu deaktivieren, stellen Sie den Parameter rds.adaptive_autovacuum jedoch auf 0 oder OFF ein.

Transaktions-ID-Wraparounds können selbst dann noch auftreten, wenn Amazon RDS die Selbstbereinigungsparameter optimiert. Wir empfehlen Ihnen, einen Amazon- CloudWatch Alarm für Transaktions-ID-Wraparounds zu implementieren. Weitere Informationen finden Sie im Beitrag Implement an Early Warning System for Transaction ID Wraparound in RDS for PostgreSQL im AWS-Database-Blog.

Wenn die adaptive Optimierung der Selbstbereinigungsparameter aktiviert ist, beginnt Amazon RDS mit der Anpassung der Selbstbereinigungsparameter, wenn die CloudWatch Metrik den Wert des autovacuum_freeze_max_age Parameters oder 500.000.000 MaximumUsedTransactionIDs erreicht, je nachdem, welcher Wert größer ist.

Amazon RDS fährt mit dem Anpassen der Parameter für die Selbstbereinigung fort, wenn eine Tabelle weiterhin zu Transaktions-ID-Wraparounds tendiert. Jede dieser Anpassungen stellt weitere Ressourcen für die Selbstbereinigung bereit, um Wraparounds zu vermeiden. Amazon RDS aktualisiert die folgenden Parameter, die sich auf die Selbstbereinigung beziehen:

RDS ändert diese Parameter nur, wenn der neue Wert die Selbstbereinigung aggressiver macht. Die Parameter werden im Arbeitsspeicher auf der DB-Instance geändert. Die Werte in der Parametergruppe werden nicht geändert. Um die aktuellen Arbeitsspeichereinstellungen anzuzeigen, verwenden Sie den PostgreSQL-SQL-Befehl SHOW.

Wenn Amazon RDS einen dieser Selbstbereinigungsparameter ändert, wird ein Ereignis für die betroffene DB-Instance erzeugt. Dieses Ereignis ist auf der AWS Management Console und über die Amazon-RDS-API sichtbar. Nachdem die MaximumUsedTransactionIDs CloudWatch Metrik unter den Schwellenwert zurückkehrt, setzt Amazon RDS die sich auf die Selbstbereinigung beziehenden Parameter im Speicher auf die in der Parametergruppe angegebenen Werte zurück. Es generiert dann ein anderes Ereignis, das dieser Änderung entspricht.

Ermittlung, ob die Tabellen in Ihrer Datenbank bereinigt werden müssen

Sie können die folgende Abfrage verwenden, um die Anzahl der nicht bereinigten Transaktionen in einer Datenbank anzuzeigen. Die Spalte datfrozenxid einer pg_database-Zeile der Datenbank ist eine Untergrenze für die normalen Transaktions-IDs, die in dieser Datenbank erscheinen. Diese Spalte ist der Mindestwert der relfrozenxid-Werte pro Tabelle in der Datenbank.

SELECT datname, age(datfrozenxid) FROM pg_database ORDER BY age(datfrozenxid) desc limit 20;

Beispielsweise könnten die Ergebnisse der Ausführung der oben gezeigten Abfrage wie folgt aussehen.

datname | age mydb | 1771757888 template0 | 1721757888 template1 | 1721757888 rdsadmin | 1694008527 postgres | 1693881061 (5 rows)

Wenn das Alter einer Datenbank 2 Milliarden Transaktions-IDs erreicht, treten Transaktions-ID (XID)-Wraparounds auf und die Datenbank wird als schreibgeschützt festgelegt. Sie können diese Abfrage verwenden, um eine Metrik zu erstellen und einige Male am Tag auszuführen. Standardmäßig ist die Selbstbereinigung so festgelegt, dass das Alter der Transaktionen 200 000 000 nicht überschreitet 200,000,000 (autovacuum_freeze_max_age).

Eine Überwachungsstrategie kann beispielsweise wie folgt aussehen:

  • Stellen Sie den autovacuum_freeze_max_age-Wert auf 200 Millionen Transaktionen ein.

  • Wenn eine Tabelle 500 Millionen nicht bereinigter Transaktionen erreicht, wird ein Alarm mit niedrigem Schweregrad ausgelöst. Dies ist kein unangemessener Wert. Er könnte jedoch zu erkennen geben, dass die Selbstbereinigung nicht Schritt hält.

  • Wenn eine Tabelle 1 Milliarde nicht bereinigter Transaktionen aufweist, sollte dies als ein Alarm behandelt werden, für den Maßnahmen zu ergreifen sind. Im Allgemeinen sollte aus Leistungsgründen das Alter möglichst nahe zu autovacuum_freeze_max_age liegen. Wir empfehlen, dass Sie eine Untersuchung unter Beachtung der folgenden Empfehlungen durchführen.

  • Wenn eine Tabelle 1,5 Milliarden nicht bereinigter Transaktionen erreicht, wird ein Alarm mit hohem Schweregrad ausgelöst. Abhängig davon, wie schnell Ihre Datenbank Transaktions-IDs verwendet, kann dieser Alarm zu erkennen geben, dass die Zeit für eine Selbstbereinigung des Systems abläuft. In diesem Fall empfehlen wir, eine unmittelbare Lösung in Betracht zu ziehen.

Wenn eine Tabelle diese Schwellenwerte konstant überschreitet, ändern Sie die Selbstbereinigungsparameter weiter. Standardmäßig ist die manuelle Verwendung von VACUUM (für den kostenbasierte Verzögerungen deaktiviert sind) aggressiver als die Standardselbstbereinigung. Der Befehl hat jedoch insgesamt auch größere Auswirkungen auf das System.

Wir empfehlen Folgendes:

Ermittlung, für welche Tabellen derzeit eine Selbstbereinigung nötig ist

Häufig benötigen eine oder zwei Tabellen eine Bereinigung. Tabellen, deren relfrozenxid-Wert größer als die Anzahl von Transaktionen in autovacuum_freeze_max_age ist, sind stets Ziel der Selbstbereinigung. Wenn andernfalls die Anzahl der Tupeln, die seit dem letzten VACUUM-Befehl veraltet sind, den Bereinigungsschwellenwert überschreitet, wird die Tabelle bereinigt.

Der Selbstbereinigungsschwellenwert ist definiert als:

Vacuum-threshold = vacuum-base-threshold + vacuum-scale-factor * number-of-tuples

wobei vacuum base thresholdautovacuum_vacuum_threshold, vacuum scale factor autovacuum_vacuum_scale_factorund number of tuples istpg_class.reltuples.

Führen Sie während der Herstellung der Verbindung mit Ihrer Datenbank die folgende Abfrage aus, um eine Liste der Tabellen anzuzeigen, für die Selbstbereinigungsfunktion eine Bereinigung als notwendig betrachtet.

WITH vbt AS (SELECT setting AS autovacuum_vacuum_threshold FROM pg_settings WHERE name = 'autovacuum_vacuum_threshold'), vsf AS (SELECT setting AS autovacuum_vacuum_scale_factor FROM pg_settings WHERE name = 'autovacuum_vacuum_scale_factor'), fma AS (SELECT setting AS autovacuum_freeze_max_age FROM pg_settings WHERE name = 'autovacuum_freeze_max_age'), sto AS (select opt_oid, split_part(setting, '=', 1) as param, split_part(setting, '=', 2) as value from (select oid opt_oid, unnest(reloptions) setting from pg_class) opt) SELECT '"'||ns.nspname||'"."'||c.relname||'"' as relation, pg_size_pretty(pg_table_size(c.oid)) as table_size, age(relfrozenxid) as xid_age, coalesce(cfma.value::float, autovacuum_freeze_max_age::float) autovacuum_freeze_max_age, (coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples) AS autovacuum_vacuum_tuples, n_dead_tup as dead_tuples FROM pg_class c join pg_namespace ns on ns.oid = c.relnamespace join pg_stat_all_tables stat on stat.relid = c.oid join vbt on (1=1) join vsf on (1=1) join fma on (1=1) left join sto cvbt on cvbt.param = 'autovacuum_vacuum_threshold' and c.oid = cvbt.opt_oid left join sto cvsf on cvsf.param = 'autovacuum_vacuum_scale_factor' and c.oid = cvsf.opt_oid left join sto cfma on cfma.param = 'autovacuum_freeze_max_age' and c.oid = cfma.opt_oid WHERE c.relkind = 'r' and nspname <> 'pg_catalog' AND (age(relfrozenxid) >= coalesce(cfma.value::float, autovacuum_freeze_max_age::float) OR coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples <= n_dead_tup) ORDER BY age(relfrozenxid) DESC LIMIT 50;

Ermittlung, ob die Selbstbereinigung derzeit ausgeführt wird und wie lange sie dauert

Wenn Sie eine Tabelle manuell bereinigen müssen, müssen Sie ermitteln, ob zurzeit eine Selbstbereinigung ausgeführt wird. Wenn dies der Fall ist, müssen Sie die Parameter anpassen, damit sie effizienter ausgeführt wird, oder die Selbstbereinigung temporär beenden, damit Sie den Befehl VACUUM manuell ausführen können.

Verwenden Sie die folgende Abfrage, um zu ermitteln, ob die Selbstbereinigung ausgeführt wird, wie lange diese bereits dauert und ob diese auf eine andere Sitzung wartet.

SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query FROM pg_stat_activity WHERE upper(query) LIKE '%VACUUM%' ORDER BY xact_start;

Nach dem Ausführen der Abfrage wird Ihnen eine Ausgabe ähnlich der folgenden angezeigt.

datname | usename | pid | state | wait_event | xact_runtime | query --------+----------+-------+--------+------------+-------------------------+-------------------------------------------------------------------------------------------------------- mydb | rdsadmin | 16473 | active | | 33 days 16:32:11.600656 | autovacuum: VACUUM ANALYZE public.mytable1 (to prevent wraparound) mydb | rdsadmin | 22553 | active | | 14 days 09:15:34.073141 | autovacuum: VACUUM ANALYZE public.mytable2 (to prevent wraparound) mydb | rdsadmin | 41909 | active | | 3 days 02:43:54.203349 | autovacuum: VACUUM ANALYZE public.mytable3 mydb | rdsadmin | 618 | active | | 00:00:00 | SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query+ | | | | | | FROM pg_stat_activity + | | | | | | WHERE query like '%VACUUM%' + | | | | | | ORDER BY xact_start; +

Verschiedene Probleme können dazu führen, dass eine Selbstbereinigungssitzung über eine lange Zeit (mehrere Tage) ausgeführt wird. Das häufigste Problem besteht jedoch darin, dass der Wert Ihres Parameters maintenance_work_mem im Verhältnis zur Größe der Tabelle oder zur Häufigkeit der Aktualisierungen zu niedrig festgelegt wurde.

Es wird empfohlen, dass Sie die folgende Formel verwenden, um den Wert des Parameters maintenance_work_mem festzulegen.

GREATEST({DBInstanceClassMemory/63963136*1024},65536)

Selbstbereinigungssitzungen, die nur kurze Zeit ausgeführt werden, können ebenfalls auf Probleme hinweisen:

  • Es kann bedeuten, dass es für Ihren Workload nicht genügend autovacuum_max_workers gibt. In diesem Fall müssen Sie die Anzahl der Worker angeben.

  • Es kann bedeuten, dass es eine Indexbeschädigung gibt (die Selbstbereinigung stürzt ab und startet bei derselben Relation neu, es gibt jedoch keine Fortschritte). Führen Sie in diesem Fall ein manuelles vacuum freeze verbose table aus, um die genaue Ursache zu sehen.

Ausführen einer manuellen Bereinigungseinfrierung

Möglicherweise möchten Sie eine manuelle Bereinigung für eine Tabelle ausführen, für die bereits ein Bereinigungsvorgang ausgeführt wird. Dies ist nützlich, wenn Sie eine Tabelle mit einem Alter identifiziert haben, das 2 Milliarden Transaktionen (oder einen Wert oberhalb eines von Ihnen beobachteten Schwellenwerts) erreicht.

Die folgenden Schritte sind Richtlinien mit mehreren Variationen des Prozesses. Angenommen, Sie stellen während der Überprüfung fest, dass der Wert für den Parameter maintenance_work_mem zu niedrig festgelegt wurde. Sie müssen sofort Maßnahmen für eine Tabelle einleiten. Sie möchten zum aktuellen Zeitpunkt jedoch keinen Bounce für die Instance auslösen. Ermitteln Sie mittels der Abfragen in vorherigen Abschnitten die Tabelle, die das Problem darstellt, und identifizieren Sie eine über einen langen Zeitraum ausgeführte Selbstbereinigungssitzung. Sie müssen die Einstellung für den Parameter maintenance_work_mem ändern. Sie müssen jedoch auch sofortige Maßnahmen einleiten und die betreffende Tabelle bereinigen. Das folgende Verfahren zeigt, was Sie in dieser Situation unternehmen.

So führen Sie manuell eine Bereinigungseinfrierung aus
  1. Öffnen Sie zwei Sitzungen für die Datenbank, die Tabelle enthält, die Sie bereinigen möchten. Verwenden Sie für die zweite Sitzung „screen“ oder ein anderes Hilfsprogramm, das die Sitzung beibehält, wenn die Verbindung verloren geht.

  2. Rufen Sie in der ersten Sitzung die Prozess-ID (PID) der Selbstbereinigungssitzung ab, die für die Tabelle ausgeführt wird.

    Führen Sie die folgende Abfrage aus, um die PID der Selbstbereinigungssitzung abzurufen.

    SELECT datname, usename, pid, current_timestamp - xact_start AS xact_runtime, query FROM pg_stat_activity WHERE upper(query) LIKE '%VACUUM%' ORDER BY xact_start;
  3. Berechnen Sie in der zweiten Sitzung die Menge des Arbeitsspeichers, den Sie für diese Operation benötigen. In diesem Beispiel ermitteln Sie, dass für diese Operation bis zu 2 GB Arbeitsspeicher verwendet werden können. Daher wird für die aktuelle Sitzung maintenance_work_mem auf 2 GB festgelegt.

    SET maintenance_work_mem='2 GB'; SET
  4. Geben Sie in der zweiten Sitzung einen vacuum freeze verbose-Befehl für die Tabelle aus. Die Verbose-Einstellung ist nützlich, da Sie Aktivität sehen können, auch wenn in PostgreSQL hierfür zurzeit kein Fortschrittsbericht verfügbar ist.

    \timing on Timing is on. vacuum freeze verbose pgbench_branches;
    INFO: vacuuming "public.pgbench_branches" INFO: index "pgbench_branches_pkey" now contains 50 row versions in 2 pages DETAIL: 0 index row versions were removed. 0 index pages have been deleted, 0 are currently reusable. CPU 0.00s/0.00u sec elapsed 0.00 sec. INFO: index "pgbench_branches_test_index" now contains 50 row versions in 2 pages DETAIL: 0 index row versions were removed. 0 index pages have been deleted, 0 are currently reusable. CPU 0.00s/0.00u sec elapsed 0.00 sec. INFO: "pgbench_branches": found 0 removable, 50 nonremovable row versions in 43 out of 43 pages DETAIL: 0 dead row versions cannot be removed yet. There were 9347 unused item pointers. 0 pages are entirely empty. CPU 0.00s/0.00u sec elapsed 0.00 sec. VACUUM Time: 2.765 ms
  5. Wenn die Selbstbereinigung die Bereinigungssitzung blockiert hat, wird Ihnen in der ersten Sitzung in pg_stat_activity angezeigt, dass das Warten für Ihre Bereinigungssitzung "T" ist. In diesem Fall müssen Sie den Selbstbereinigungsvorgang wie folgt beenden.

    SELECT pg_terminate_backend('the_pid');

    An diesem Punkt beginnt Ihre Sitzung. Es ist wichtig, zu beachten, dass die Selbstbereinigung sofort neu gestartet wird, da diese Tabelle in der Liste der Aufgaben wahrscheinlich ganz oben steht.

  6. Initiieren Sie Ihren vacuum freeze verbose-Befehl in der zweiten Sitzung und beenden Sie dann den Selbstbereinigungsvorgang in der ersten Sitzung.

Neuindizierung einer Tabelle während der Ausführung einer Selbstbereinigung

Wenn ein Index beschädigt wurde, verarbeitet die Selbstbereinigung die Tabelle weiter und schlägt fehl. Wenn Sie in dieser Situation eine manuelle Bereinigung versuchen, werden Sie eine Fehlermeldung ähnlich der folgenden erhalten.

postgres=> vacuum freeze pgbench_branches; ERROR: index "pgbench_branches_test_index" contains unexpected zero page at block 30521 HINT: Please REINDEX it.

Wenn der Index beschädigt ist und eine Selbstbereinigung für die Tabelle versucht wird, konkurrieren Sie mit einer Selbstbereinigungssitzung, die bereits ausgeführt wird. Wenn Sie einen REINDEX-Befehl ausgeben, wird eine exklusive Sperre für die Tabelle ausgeführt. Schreiboperationen werden blockiert. Gleiches gilt für Lesevorgänge, die diesen spezifischen Index verwenden.

So führen Sie eine Neuindizierung für eine Tabelle aus, wenn eine Selbstbereinigung für die Tabelle ausgeführt wird
  1. Öffnen Sie zwei Sitzungen für die Datenbank, die Tabelle enthält, die Sie bereinigen möchten. Verwenden Sie für die zweite Sitzung „screen“ oder ein anderes Hilfsprogramm, das die Sitzung beibehält, wenn die Verbindung verloren geht.

  2. Rufen Sie in der ersten Sitzung die PID der Selbstbereinigungssitzung ab, die für die Tabelle ausgeführt wird.

    Führen Sie die folgende Abfrage aus, um die PID der Selbstbereinigungssitzung abzurufen.

    SELECT datname, usename, pid, current_timestamp - xact_start AS xact_runtime, query FROM pg_stat_activity WHERE upper(query) like '%VACUUM%' ORDER BY xact_start;
  3. Führen Sie in der zweiten Sitzung den Neuindizierungsbefehl aus.

    \timing on Timing is on. reindex index pgbench_branches_test_index; REINDEX Time: 9.966 ms
  4. Wenn die Selbstbereinigung den Prozess blockiert hat, wird Ihnen in der ersten Sitzung in pg_stat_activity angezeigt, dass das Warten für Ihre Bereinigungssitzung "T" ist. In diesem Fall beenden Sie den Selbstbereinigungsprozess.

    SELECT pg_terminate_backend('the_pid');

    An diesem Punkt beginnt Ihre Sitzung. Es ist wichtig, zu beachten, dass die Selbstbereinigung sofort neu gestartet wird, da diese Tabelle in der Liste der Aufgaben wahrscheinlich ganz oben steht.

  5. Initiieren Sie Ihren Befehl in der zweiten Sitzung und beenden Sie dann den Selbstbereinigungsvorgang in der ersten Sitzung.

Verwalten der automatischen Bereinigung mit großen Indizes

Im Rahmen ihrer Funktion führt die automatische Bereinigung mehrere Bereinigungsphasen aus, während sie für eine Tabelle ausgeführt wird. Bevor die Tabelle bereinigt wird, werden zunächst alle Indizes bereinigt. Wenn mehrere große Indizes entfernt werden, benötigt diese Phase einen großen Zeit- und Ressourcenaufwand. Es hat sich daher bewährt, die Anzahl der Indizes in einer Tabelle zu kontrollieren und ungenutzte Indizes zu entfernen.

Überprüfen Sie für diesen Vorgang zunächst die Gesamtindexgröße. Stellen Sie dann fest, ob es möglicherweise unbenutzte Indizes gibt, die entfernt werden können, wie in den folgenden Beispielen dargestellt.

So überprüfen Sie die Größe der Tabelle und ihrer Indizes

postgres=> select pg_size_pretty(pg_relation_size('pgbench_accounts')); pg_size_pretty 6404 MB (1 row)
postgres=> select pg_size_pretty(pg_indexes_size('pgbench_accounts')); pg_size_pretty 11 GB (1 row)

In diesem Beispiel ist die Größe der Indizes größer als die Tabelle. Dieser Unterschied kann zu Leistungsproblemen führen, da die Indizes überlastet oder ungenutzt sind, was sich sowohl auf die automatische Bereinigung als auch auf Insert-Operationen auswirkt.

So prüfen Sie, ob ungenutzte Indizes vorhanden sind

Mithilfe der Ansicht pg_stat_user_indexes können Sie überprüfen, wie oft ein Index für die Spalte idx_scan verwendet wird. Im folgenden Beispiel haben die ungenutzten Indizes den idx_scan-Wert 0.

postgres=> select * from pg_stat_user_indexes where relname = 'pgbench_accounts' order by idx_scan desc; relid | indexrelid | schemaname | relname | indexrelname | idx_scan | idx_tup_read | idx_tup_fetch -------+------------+------------+------------------+-----------------------+----------+--------------+--------------- 16433 | 16454 | public | pgbench_accounts | index_f | 6 | 6 | 0 16433 | 16450 | public | pgbench_accounts | index_b | 3 | 199999 | 0 16433 | 16447 | public | pgbench_accounts | pgbench_accounts_pkey | 0 | 0 | 0 16433 | 16452 | public | pgbench_accounts | index_d | 0 | 0 | 0 16433 | 16453 | public | pgbench_accounts | index_e | 0 | 0 | 0 16433 | 16451 | public | pgbench_accounts | index_c | 0 | 0 | 0 16433 | 16449 | public | pgbench_accounts | index_a | 0 | 0 | 0 (7 rows)
postgres=> select schemaname, relname, indexrelname, idx_scan from pg_stat_user_indexes where relname = 'pgbench_accounts' order by idx_scan desc; schemaname | relname | indexrelname | idx_scan ------------+------------------+-----------------------+---------- public | pgbench_accounts | index_f | 6 public | pgbench_accounts | index_b | 3 public | pgbench_accounts | pgbench_accounts_pkey | 0 public | pgbench_accounts | index_d | 0 public | pgbench_accounts | index_e | 0 public | pgbench_accounts | index_c | 0 public | pgbench_accounts | index_a | 0 (7 rows)
Anmerkung

Diese Statistiken sind ab dem Zeitpunkt, an dem die Statistiken zurückgesetzt werden, inkrementell. Angenommen, Sie haben einen Index, der nur am Ende eines Geschäftsquartals oder nur für einen bestimmten Bericht verwendet wird. Es ist möglich, dass dieser Index seit dem Zurücksetzen der Statistiken nicht mehr verwendet wurde. Weitere Informationen finden Sie unter Statistikfunktionen. Indizes, die verwendet werden, um Eindeutigkeit zu erzwingen, werden nicht gescannt und sollten nicht als ungenutzte Indizes identifiziert werden. Um die ungenutzten Indizes zu identifizieren, sollten Sie über fundierte Kenntnisse der Anwendung und ihrer Abfragen verfügen.

Um zu überprüfen, wann die Statistiken für eine Datenbank zuletzt zurückgesetzt wurden, verwenden Sie pg_stat_database.

postgres=> select datname, stats_reset from pg_stat_database where datname = 'postgres'; datname | stats_reset ----------+------------------------------- postgres | 2022-11-17 08:58:11.427224+00 (1 row)

Möglichst schnelles Bereinigen einer Tabelle

RDS für PostgreSQL 12 und höher

Wenn Sie zu viele Indizes in einer großen Tabelle haben, nähert sich Ihre DB-Instance möglicherweise dem Transaktions-ID-Wraparound (XID), also dem Zeitpunkt, an dem der XID-Zähler auf Null zurückgeht. Wenn diese Option nicht aktiviert ist, kann diese Situation zu Datenverlust führen. Sie können die Tabelle jedoch schnell bereinigen, ohne die Indizes zu bereinigen. In RDS für PostgreSQL 12 und höher können Sie VACUUM mit der Klausel INDEX_CLEANUP verwenden.

postgres=> VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) pgbench_accounts; INFO: vacuuming "public.pgbench_accounts" INFO: table "pgbench_accounts": found 0 removable, 8 nonremovable row versions in 1 out of 819673 pages DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 7517 Skipped 0 pages due to buffer pins, 0 frozen pages. CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s.

Wenn eine automatische Bereinigungssitzung bereits läuft, müssen Sie sie beenden, um mit dem manuellen VACUUM-Vorgang zu beginnen. Informationen zur Ausführung manueller Bereinigungseinfrierungen finden Sie unter Ausführen einer manuellen Bereinigungseinfrierung.

Anmerkung

Wenn Sie die Indexbereinigung regelmäßig überspringen, kann dies zu einer Überlastung der des Indizes führen, was sich auf die gesamte Scanleistung auswirkt. Verwenden Sie das vorherige Verfahren am besten nur, um einen Transaktions-ID-Wraparound zu verhindern.

RDS für PostgreSQL 11 und niedriger

In RDS für PostgreSQL 11 und niedrigeren Versionen besteht die einzige Möglichkeit, den Bereinigungsvorgang schneller abzuschließen, darin, die Anzahl der Indizes in einer Tabelle zu reduzieren. Das Löschen eines Index kann sich auf Abfragepläne auswirken. Wir empfehlen, zuerst unbenutzte Indizes zu löschen und dann die Indizes löschen, wenn der XID-Wraparound kurz bevorsteht. Nach Abschluss des Bereinigungsvorgangs können Sie diese Indizes neu erstellen.

Weitere Parameter, die sich auf die Selbstbereinigung auswirken

Die folgende Abfrage zeigt die Werte einiger Parameter an, die sich direkt auf die Selbstbereinigung und ihr Verhalten auswirken. Die Selbstbereinigungsparameter werden in der PostgreSQL-Dokumentation vollständig beschrieben.

SELECT name, setting, unit, short_desc FROM pg_settings WHERE name IN ( 'autovacuum_max_workers', 'autovacuum_analyze_scale_factor', 'autovacuum_naptime', 'autovacuum_analyze_threshold', 'autovacuum_analyze_scale_factor', 'autovacuum_vacuum_threshold', 'autovacuum_vacuum_scale_factor', 'autovacuum_vacuum_threshold', 'autovacuum_vacuum_cost_delay', 'autovacuum_vacuum_cost_limit', 'vacuum_cost_limit', 'autovacuum_freeze_max_age', 'maintenance_work_mem', 'vacuum_freeze_min_age');

All diese Parameter wirken sich auf die Selbstbereinigung aus. Die wichtigsten unter ihnen sind jedoch:

Festlegen von Selbstbereinigungsparametern auf Tabellenebene

Sie können Speicherparameter, die sich auf die der Selbstbereinigung beziehen, auf Tabellenebene festlegen. Dies kann im Vergleich zur Änderung des Verhaltens der gesamten Datenbank ein bevorzugtes Verfahren sein. Im Fall großer Tabellen müssen möglicherweise aggressive Einstellungen festgelegt werden, und Sie möchten vielleicht nicht, dass sich die Selbstbereinigung für alle Tabellen auf diese Weise verhält.

Die folgende Abfrage zeigt, für welche Tabellen zurzeit Optionen auf Tabellenebene festgelegt wurden.

SELECT relname, reloptions FROM pg_class WHERE reloptions IS NOT null;

Ein Beispiel, in dem dies nützlich sein kann, sind Tabellen, die sehr viel größer als Ihre restlichen Tabellen sind. Angenommen, es gibt eine Tabelle mit 300 GB und 30 weitere Tabellen mit weniger als 1 GB. In diesem Fall würde es sich anbieten, einige spezifische Parameter nur für die große Tabelle festzulegen, um nicht das Verhalten des gesamten Systems zu ändern.

ALTER TABLE mytable set (autovacuum_vacuum_cost_delay=0);

Hierdurch wird die kostenbasierte Selbstbereinigungsverzögerung für diese Tabelle auf Kosten einer größeren Ressourcennutzung in Ihrem System deaktiviert. Normalerweise pausiert die Selbstbereinigung für autovacuum_vacuum_cost_delay jedes Mal, wenn autovacuum_cost_limit erreicht wird. Weitere Details finden Sie in der PostgreSQL-Dokumentation zum Thema kostenbasierte Bereinigung.

Protokollieren von Selbstbereinigung- und Bereinigungsaktivitäten

Informationen über Bereinigungsaktivitäten werden basierend auf der imrds.force_autovacuum_logging_level-Parameter angegebenen Ebene an das postgresql.log gesendet. Im Folgenden sind die für diesen Parameter zulässigen Werte und die PostgreSQL-Versionen aufgeführt, für die dieser Wert die Standardeinstellung ist:

  • disabled (PostgreSQL 10, PostgreSQL 9.6)

  • debug5, debug4, debug3, debug2, debug1

  • info (PostgreSQL 12, PostgreSQL 11)

  • notice

  • warning (PostgreSQL 13 und höher)

  • error, Protokoll, fatal, panic

Das rds.force_autovacuum_logging_level arbeitet mit dem log_autovacuum_min_duration-Parameter. Der Wert des log_autovacuum_min_duration-Parameters ist der Schwellenwert (in Millisekunden), über dem Selbstbereinigung-Aktionen protokolliert werden. Eine Einstellung von -1 protokolliert nichts, während eine Einstellung von 0 alle Aktionen protokolliert. Wie bei rds.force_autovacuum_logging_level, Standardwerte für log_autovacuum_min_duration sind versionsabhängig wie folgt:

  • 10000 ms – PostgreSQL 14, PostgreSQL 13, PostgreSQL 12 und PostgreSQL 11

  • (empty) – Kein Standardwert für PostgreSQL 10 und PostgreSQL 9.6

Wir empfehlen Ihnen, rds.force_autovacuum_logging_level auf WARNING einzustellen. Wir empfehlen auch, dass Sie log_autovacuum_min_duration auf einen Wert von 1000 bis 5000 einstellen. Eine Einstellung von 5000 Protokollaktivitäten, die länger als 5000 Millisekunden dauern. Jede andere Einstellung als –1 protokolliert auch Meldungen, wenn die Selbstbereinigungsaktion aufgrund einer widersprüchlichen Sperre oder gleichzeitig verworfener Beziehungen übersprungen wird. Weitere Informationen finden Sie unter Selbstbereinigung in der PostgreSQL-Dokumentation.

Um Probleme zu beheben, können Sie die rds.force_autovacuum_logging_level-Parameter in eine der Debugebenen ändern, von debug1 bis zu debug5 für die ausführlichsten Informationen. Wir empfehlen, die Debug-Einstellungen für kurze Zeiträume und nur zur Fehlerbehebung zu verwenden. Weitere Informationen finden Sie unter Zeitpunkt des Protokollierens in der PostgreSQL-Dokumentation.

Anmerkung

PostgreSQL ermöglicht es dem Konto rds_superuser, Autovakuum-Sitzungen in pg_stat_activity anzuzeigen. Sie können beispielsweise eine Selbstbereinigungssitzung identifizieren und beenden, die die Ausführung eines Befehls blockiert oder langsamer als ein manuell ausgegebener Bereinigungsbefehl ausgeführt wird.