Ausführungszeit von PostgreSQL ANALYZE über 24 Stunden (läuft noch)


7

Ich habe ein Postgres DB 9.3.2 -> 10.5 mit pg_upgrade (an Ort und Stelle) aktualisiert. Ich habe alles gemäß der Dokumentation und den Anweisungen von pg_upgrade gemacht. Alles lief gut, aber dann wurde mir klar, dass die Indizes nicht in einer der Tabellen verwendet wurden (möglicherweise sind auch andere betroffen).

Also habe ich ANALYZEgestern einen Tisch gestartet , der noch läuft (seit über 22h) ...!

Die Frage: Ist es normal ANALYZE, eine so lange Ausführungszeit zu haben?

Die Tabelle enthält ungefähr 30 Millionen Datensätze. Die Struktur ist:

CREATE TABLE public.chs_contact_history_events (
    event_id bigint NOT NULL
           DEFAULT nextval('chs_contact_history_events_event_id_seq'::regclass),
    chs_id integer NOT NULL,
    event_timestamp bigint NOT NULL,
    party_id integer NOT NULL,
    event integer NOT NULL,
    cause integer NOT NULL,
    text text COLLATE pg_catalog."default",
    timestamp_offset integer,
    CONSTRAINT pk_contact_history_events PRIMARY KEY (event_id)
);

ALTER TABLE public.chs_contact_history_events OWNER to c_chs;

CREATE INDEX ix_chs_contact_history_events_chsid
    ON public.chs_contact_history_events USING hash (chs_id)
    TABLESPACE pg_default;

CREATE INDEX ix_chs_contact_history_events_id
    ON public.chs_contact_history_events USING btree (event_id)
    TABLESPACE pg_default;

CREATE INDEX ix_history_events_partyid
    ON public.chs_contact_history_events USING hash (party_id)
    TABLESPACE pg_default;

AKTUALISIEREN:

Ich habe die folgende Abfrage ausgeführt, um die aktuell ausgeführten Prozesse zu erhalten und mehr als interessante Ergebnisse zu erzielen:

SELECT pid, now() - pg_stat_activity.query_start AS duration, query, state
FROM pg_stat_activity
WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes'
AND state = 'active';

Anormal laufende Abfragen für diese Tabelle

Es scheint, dass die Wartungsaufgaben und die gleichzeitige Neuerstellung der Indextabelle eingefroren sind!

Die nächste Frage lautet also: Ist es sicher, diese Prozesse abzubrechen? Und was als nächstes zu tun? IMO wird sie alle stoppen und die Indexerstellung neu starten, aber ich bin mir nicht sicher.


ANHANG 1

Möglicherweise verwandte Fehler in Version 9 korrigiert:

9.3.7 und 9.4.2 Behebung eines möglichen Fehlers während der Aufteilung des Hash-Index-Buckets, wenn andere Prozesse den Index gleichzeitig ändern

9.3.18 und 9.4.13 sowie 9.5.8 und 9.6.4 Korrigieren Sie die Beschädigung der gemeinsam genutzten Prädikatsperr-Hash-Tabelle mit geringer Wahrscheinlichkeit in Windows-Builds

9.5.4 Fehler beim Erstellen großer Hash-Indizes (größer als shared_buffers) behoben Der für große Indizes verwendete Codepfad enthielt einen Fehler, der dazu führte, dass falsche Hash-Werte in den Index eingefügt wurden, sodass nachfolgende Indexsuchen immer fehlschlugen, mit Ausnahme von Tupeln, die in den Index eingefügt wurden nach dem ersten Build.

Möglicherweise verwandte Fehler in Version 10 korrigiert:

10.2 Fehler behoben, bei dem die Metapage eines Hash-Index nach dem Hinzufügen einer neuen Überlaufseite als fehlerhaft markiert wurde, was möglicherweise zu einer Beschädigung des Index führte

Verhindern Sie Speicherausfälle aufgrund von übermäßigem Wachstum einfacher Hash-Tabellen


Und last but not least macht mir das Sorgen (da ein Upgrade in der produktiven Umgebung nicht realistisch zu sein scheint):

10.6 Vermeiden Sie ein Überlaufen der Metapage eines Hash-Index, wenn BLCKSZ kleiner als die Standardeinstellung ist

Behebung von Aktualisierungen der fehlenden Seitenprüfsumme in Hash-Indizes


ANHANG 2

Upgrade-Anleitung in Version 10:

Hash-Indizes müssen nach pg_upgrade von einer früheren Hauptversion von PostgreSQL neu erstellt werden

Wesentliche Verbesserungen des Hash-Index machten diese Anforderung erforderlich. pg_upgrade erstellt dazu ein Skript.

Beachten Sie, dass ich dieses Skript natürlich zum Zeitpunkt des Upgrades ausgeführt habe.


1
Ich habe versucht, die Frage mit so vielen Informationen wie möglich zu aktualisieren. Unter anderem mit einem seltsamen Ergebnis unter den aktuell laufenden Abfragen.
Wjozsi

2
Oh, es ist ein bisschen chaotisch. Ist dieser Index gleichzeitig Teil des von Ihnen erwähnten Skripts oder haben Sie ihn manuell ausgeführt? Im Nachhinein sollten Sie zuerst auf die neueste Version 9.3 (9.3.25, glaube ich) und dann die Hauptversion (auf 10) aktualisiert haben. Da 9.3.2 sehr alt war, ist das Upgrade kleinerer Versionen ziemlich unproblematisch. Aber was getan wird, wird getan, das Problem ist, einen Ausweg aus dem Chaos zu finden!
Ypercubeᵀᴹ

1
Ich denke, Sie können ANALYZE-Befehle sicher beenden und auch das Autovakuum besser deaktivieren. Warten Sie dann, bis der gleichzeitige Index abgeschlossen ist. Wenn dies nicht der Fall ist, müssen Sie möglicherweise auch das töten (und dann sehen, was zu tun ist). Haben Sie ein Skript, mit dem Sie bei Bedarf alle Hash-Indizes löschen und neu erstellen können?
Ypercubeᵀᴹ

1
Zuerst würde ich neue Verbindungen zur Datenbank verbieten (wenn dies eine Option ist). Siehe: dba.stackexchange.com/a/11895/3684 . Dann würde ich den CREATE INDEX CONCURRENTLYProzess beenden, der hier der Schuldige zu sein scheint. Dann , wenn die manuelle ANALYZEund autovacuumnoch nicht nach einiger Zeit nicht beenden kann, töten diejenigen, auch. Dann würde ich fehlerhaften RAM auf dem Server ausschließen. Dann würde ich alle Hash-Indizes vollständig löschen, den DB-Cluster neu starten (falls dies eine Option ist) und auf die neueste Version von Postgres 10.6 (zwei weitere kleinere Korrekturen für Hash-Indizes) oder 11.1 aktualisieren. Erstellen Sie dann nicht alle Hash-Indizes neu CONCURRENTLY.
Erwin Brandstetter

1
Die Art und Weise, wie Sie sich auf "v9 und" v10 "beziehen, weist darauf hin, dass Sie die Definition der Hauptversion in Postgres möglicherweise nicht vollständig kennen. Verstehen Sie sie unbedingt, da sie für Ihre Situation relevant ist. Zitieren Sie die offizielle Versionsrichtlinie Starting with PostgreSQL 10, a major version is indicated by increasing the first part of the version, e.g. 10 to 11. Before PostgreSQL 10, a major version was indicated by increasing either the first or second part of the version number, e.g. 9.5 to 9.6.
Erwin Brandstetter,

Antworten:


6

Nach mehreren Stunden Recherche und Untersuchung der aktuellen Situation habe ich es geschafft, das Problem zu lösen. (Vielen Dank an den Mitbenutzer ypercube für die Inspiration und an Erwin Brandstetter, der parallel zur gleichen Lösung gekommen ist.)

Es gab also mehrere Schichten des Problems.

1.) UPGRADE

Das Upgrade mit pg_upgrade 9.3.2 -> 10.5 sollte in zwei Schritten erfolgen. Zuerst in derselben Zeile (9.3.2 -> 9.3.25) und dann zu 10.x (in meinem Fall 10.5)

Ich habe ein direktes Upgrade durchgeführt und es scheint, dass dies die Hauptursache für das Problem war.

2.) HASH INDEXES

Es scheint, dass Hash-Indizes unter einigen seltsamen Fehlern in Postgres litten, die bereits korrigiert wurden, aber die Verwendung von Indizes der Vorkorrekturversionen zu Fehlern führt

3.) GEFRORENE AUFGABEN

Es ist sinnvoll, nach Postgres-Prozessen zu suchen, die lange Zeit nicht realistisch sind. (Siehe Abfrage in der Frage.) In meinem Fall stellte sich heraus, dass die Neuerstellung von Indizes irgendwie hängen blieb und mehrere andere Aufgaben ebenfalls blockiert wurden.

Es ist sicher, die meisten von ihnen abzubrechen, SELECT pg_cancel_backend(__pid__);wobei pid die Prozess-ID ist, die in der Ergebnismenge der zuvor genannten Abfrage gefunden wurde. Also habe ich es getan. Ich habe sogar die Autovakuumprozesse gestoppt.

4.) SPEICHERHANDHABUNG

Als ich nach all dem endlich dachte, ich könnte die neuen Indizes löschen und erstellen, stand ich vor dem nächsten Problem. Nach ungefähr einer Minute wurden alle Wartungsabfragen mit einer Fehlermeldung beendet:

ERROR: out of memory
DETAIL: Failed on request of size 22355968.
SQL state: 53200

Es scheint, dass sich die Speicherbehandlung zwischen 9.3 und 10 geändert hat. Ich musste die Menge an wartungs_mem in der Konfiguration reduzieren :

maintenance_work_mem = 64MB     # min 1MB

Es war vorher 512 MB groß und obwohl der Server 32 GB RAM hat, funktionierte es immer noch nicht damit.

5.) ERHOLUNG VON INDEXEN

Immerhin war es möglich, Indizes neu zu erstellen (alte löschen und neue erstellen). Mit einem richtigen Skript wäre es einfacher gewesen, aber ich musste es manuell tun. Vergessen Sie nicht, dass das Erstellen und Löschen von Indizes die Tabelle sperrt. In einer produktiven Umgebung (wie meiner) sollten Sie dies KONZURRENT tun.

Bearbeiten:

Ich erkannte auch, dass die Verwendung von Hash-Indizes in meinem speziellen Fall nicht wirklich sinnvoll war, und beschloss, sie bei der Neuerstellung in btree zu ändern.

6.) ANALYSE

Nach der Neuerstellung der Indizes muss eine Analyse der betroffenen Tabellen (oder der gesamten Datenbank) durchgeführt werden. Nach all den oben genannten Aktionen läuft es selbst in einer riesigen Datenbank wie meiner überraschend schnell.

Die Indizes werden wieder verwendet und die Leistung ist wieder perfekt. Dies ist also ein Happy End in meinem ersten StackExchange-Beitrag. :-)


2
Nebenbei: Der Speicherfehler war wahrscheinlich das Ergebnis der parallelen Erstellung vieler Indizes. Für einzelne große Operationen sollten Sie immer noch viel mehr als 64 MB haben, maintenance_work_memwenn Sie 20 Millionen Zeilen verarbeiten. Sie können es pro Sitzung oder sogar Transaktion mit SET/ festlegen SET LOCAL.
Erwin Brandstetter

1
Bitte denken Sie daran , dies zu gegebener Zeit als die richtige Antwort zu akzeptieren .
Michael Green
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.