PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL läuft langsam? Tipps &Tricks, um zur Quelle zu gelangen

Als PostgreSQL-Datenbankadministrator gibt es die täglichen Erwartungen, Backups zu überprüfen, DDL-Änderungen anzuwenden, sicherzustellen, dass die Protokolle keine bahnbrechenden FEHLER enthalten, und panische Anrufe von Entwicklern zu beantworten, deren Berichte doppelt so lange laufen wie normal und sie in zehn Minuten ein Meeting haben.

Selbst mit einem guten Verständnis des Zustands verwalteter Datenbanken werden immer neue Fälle und neue Probleme in Bezug auf die Leistung und das „Gefühl“ der Datenbank auftauchen. Unabhängig davon, ob es sich um eine panische E-Mail oder ein offenes Ticket für „die Datenbank fühlt sich langsam“ handelt, kann dieser häufigen Aufgabe im Allgemeinen mit wenigen Schritten gefolgt werden, um zu überprüfen, ob ein Problem mit PostgreSQL vorliegt oder nicht, und was dieses Problem sein könnte.

Dies ist weder eine erschöpfende Anleitung, noch müssen die Schritte in einer bestimmten Reihenfolge ausgeführt werden. Aber es handelt sich eher um eine Reihe von ersten Schritten, die unternommen werden können, um die häufigsten Übeltäter schnell zu finden und neue Erkenntnisse darüber zu gewinnen, was das Problem sein könnte. Ein Entwickler weiß möglicherweise, wie sich die Anwendung verhält und reagiert, aber der Datenbankadministrator weiß, wie sich die Datenbank verhält und auf die Anwendung reagiert, und gemeinsam kann das Problem gefunden werden.

HINWEIS: Die auszuführenden Abfragen sollten als Superuser ausgeführt werden, z. B. „postgres“ oder ein beliebiger Datenbankbenutzer, dem die Superuser-Berechtigungen erteilt wurden. Eingeschränkte Benutzer werden entweder verweigert oder Daten werden weggelassen.

Schritt 0 – Informationsbeschaffung

Holen Sie so viele Informationen wie möglich von jedem ein, der sagt, dass die Datenbank langsam zu sein scheint; spezifische Abfragen, verbundene Anwendungen, Zeiträume der Leistungsverlangsamung usw. Je mehr Informationen sie geben, desto einfacher wird es, das Problem zu finden.

Schritt 1 - Überprüfen Sie pg_stat_activity

Die Anfrage kann in vielen verschiedenen Formen auftreten, aber wenn „Langsamkeit“ das allgemeine Problem ist, ist die Überprüfung von pg_stat_activity der erste Schritt, um zu verstehen, was vor sich geht. Die Ansicht pg_stat_activity (Dokumentation für jede Spalte in dieser Ansicht finden Sie hier) enthält eine Zeile für jeden Serverprozess / jede Verbindung zur Datenbank von einem Client. Diese Ansicht enthält einige hilfreiche Informationen.

HINWEIS: Es ist bekannt, dass pg_stat_activity die Struktur im Laufe der Zeit ändert und die präsentierten Daten verfeinert. Das Verständnis der Spalten selbst wird dazu beitragen, Abfragen je nach Bedarf in Zukunft dynamisch zu erstellen.

Bemerkenswerte Spalten in pg_stat_activity sind:

  1. Abfrage:Eine Textspalte, die die Abfrage anzeigt, die gerade ausgeführt wird, auf die Ausführung wartet oder zuletzt ausgeführt wurde (je nach Status). Dies kann dabei helfen, festzustellen, welche Abfragen ein Entwickler möglicherweise langsam ausführt.
  2. client_addr:Die IP-Adresse, von der diese Verbindung und Abfrage stammt. Wenn leer (oder Null), stammt es von localhost.
  3. backend_start, xact_start, query_start:Diese drei liefern jeweils einen Zeitstempel, wann sie gestartet wurden. Backend_start stellt dar, wann die Verbindung zur Datenbank hergestellt wurde, xact_start ist, wann die aktuelle Transaktion gestartet wurde, und query_start ist, wann die aktuelle (oder letzte) Abfrage gestartet wurde.
  4. state:Der Zustand der Verbindung zur Datenbank. Aktiv bedeutet, dass gerade eine Abfrage ausgeführt wird, „idle“ bedeutet, dass auf weitere Eingaben vom Client gewartet wird, „idle in transaction“ bedeutet, dass auf weitere Eingaben vom Client gewartet wird, während eine offene Transaktion gehalten wird. (Es gibt andere, aber ihre Wahrscheinlichkeit ist selten, konsultieren Sie die Dokumentation für weitere Informationen).
  5. Datenname:Der Name der Datenbank, mit der die Verbindung derzeit verbunden ist. In Clustern mit mehreren Datenbanken kann dies helfen, problematische Verbindungen zu isolieren.
  6. wait_event_type und wait_event:Diese Spalten sind null, wenn eine Abfrage nicht wartet, aber wenn sie wartet, enthalten sie Informationen darüber, warum die Abfrage wartet, und die Untersuchung von pg_locks kann identifizieren, worauf sie wartet. (PostgreSQL 9.5 und früher hat nur eine boolesche Spalte mit dem Namen „waiting“, wahr, wenn gewartet wird, falsch, wenn nicht.

1.1. Wartet / blockiert die Abfrage?

Wenn eine bestimmte Abfrage oder Abfragen „langsam“ oder „hängen“ sind, überprüfen Sie, ob sie auf den Abschluss einer anderen Abfrage warten. Aufgrund der Beziehungssperre können andere Abfragen eine Tabelle sperren und anderen Abfragen den Zugriff auf Daten oder deren Änderung verweigern, bis diese Abfrage oder Transaktion abgeschlossen ist.

PostgreSQL 9.5 und früher:

SELECT * FROM pg_stat_activity WHERE waiting = TRUE;

PostgreSQL 9.6:

SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL;

PostgreSQL 10 und höher (?):

SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL AND backend_type = 'client backend';

Die Ergebnisse dieser Abfrage zeigen alle Verbindungen, die derzeit auf eine andere Verbindung warten, um Sperren für eine benötigte Relation freizugeben.

Wenn die Abfrage von einer anderen Verbindung blockiert wird, gibt es einige Möglichkeiten, diese herauszufinden. In PostgreSQL 9.6 und höher ermöglicht die Funktion pg_blocking_pids() die Eingabe einer Prozess-ID, die blockiert wird, und gibt ein Array von Prozess-IDs zurück, die für die Blockierung verantwortlich sind.

PostgreSQL 9.6 und höher:

SELECT * FROM pg_stat_activity 
WHERE pid IN (SELECT pg_blocking_pids(<pid of blocked query>));

PostgreSQL 9.5 und früher:

SELECT blocked_locks.pid     AS blocked_pid,
         blocked_activity.usename  AS blocked_user,
         blocking_locks.pid     AS blocking_pid,
         blocking_activity.usename AS blocking_user,
         blocked_activity.query    AS blocked_statement,
         blocking_activity.query   AS current_statement_in_blocking_process
   FROM  pg_catalog.pg_locks         blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks         blocking_locks 
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
   WHERE NOT blocked_locks.GRANTED;

(Verfügbar im PostgreSQL-Wiki).

Diese Abfragen verweisen auf das, was eine bestimmte bereitgestellte PID blockiert. Damit kann eine Entscheidung getroffen werden, die blockierende Abfrage oder Verbindung zu beenden oder laufen zu lassen.

Schritt 2 – Wenn die Abfragen ausgeführt werden, warum dauern sie so lange?

2.1. Führt der Planer Abfragen effizient aus?

Wenn eine fragliche Abfrage (oder eine Gruppe von Abfragen) den Status „aktiv“ hat, wird sie tatsächlich ausgeführt. Wenn die gesamte Abfrage nicht in pg_stat_activity verfügbar ist, rufen Sie sie von den Entwicklern oder dem Postgresql-Protokoll ab und beginnen Sie mit der Erkundung des Abfrageplaners.

EXPLAIN SELECT * FROM postgres_stats.table_stats t JOIN hosts h ON (t.host_id = h.host_id) WHERE logged_date >= '2018-02-01' AND logged_date < '2018-02-04' AND t.india_romeo = 569;
Nested Loop  (cost=0.280..1328182.030 rows=2127135 width=335)
  ->  Index Scan using six on victor_oscar echo  (cost=0.280..8.290 rows=1 width=71)
          Index Cond: (india_romeo = 569)
  ->  Append  (cost=0.000..1306902.390 rows=2127135 width=264)
        ->  Seq Scan on india_echo romeo  (cost=0.000..0.000 rows=1 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on juliet victor_echo  (cost=0.000..437153.700 rows=711789 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on india_papa quebec_bravo  (cost=0.000..434936.960 rows=700197 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on two oscar  (cost=0.000..434811.720 rows=715148 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))

Dieses Beispiel zeigt einen Abfrageplan für einen Join aus zwei Tabellen, der auch auf eine partitionierte Tabelle trifft. Wir suchen nach allem, was dazu führen kann, dass die Abfrage langsam wird, und in diesem Fall führt der Planer mehrere sequenzielle Scans auf Partitionen durch, was darauf hindeutet, dass ihnen Indizes fehlen. Das Hinzufügen von Indizes zu diesen Tabellen für die Spalte „india_romeo“ wird diese Abfrage sofort verbessern.

Dinge, auf die Sie achten sollten, sind sequentielle Scans, verschachtelte Schleifen, teure Sortierung usw. Das Verständnis des Abfrageplaners ist entscheidend, um sicherzustellen, dass Abfragen die bestmögliche Leistung erbringen. Weitere Informationen finden Sie hier.

2.2. Sind die beteiligten Tabellen aufgebläht?

Wenn sich die Abfragen immer noch langsam anfühlen, ohne dass der Abfrageplaner auf etwas Offensichtliches hinweist, ist es an der Zeit, den Zustand der betroffenen Tabellen zu überprüfen. Sind sie zu groß? Sind sie aufgebläht?

SELECT n_live_tup, n_dead_tup from pg_stat_user_tables where relname = ‘mytable’;
n_live_tup  | n_dead_tup
------------+------------
      15677 |    8275431
(1 row)

Hier sehen wir, dass es viel mehr tote Zeilen als aktive Zeilen gibt, was bedeutet, dass die Engine, um die richtigen Zeilen zu finden, Daten durchsuchen muss, die nicht einmal relevant sind, um echte Daten zu finden. Ein Vakuum / Vakuum voll auf diesem Tisch wird die Leistung erheblich steigern.

Schritt 3 – Überprüfen Sie die Protokolle

Wenn das Problem immer noch nicht gefunden werden kann, überprüfen Sie die Protokolle auf Hinweise.

FATAL / ERROR-Meldungen:

Suchen Sie nach Nachrichten, die möglicherweise Probleme verursachen, z. B. Deadlocks oder lange Wartezeiten, um eine Sperre zu erhalten.

Kontrollpunkte

Hoffentlich ist log_checkpoints auf on gesetzt, wodurch Prüfpunktinformationen in die Protokolle geschrieben werden. Es gibt zwei Arten von Checkpoints, zeitgesteuert und angefordert (erzwungen). Wenn Checkpoints erzwungen werden, müssen schmutzige Puffer im Speicher auf die Festplatte geschrieben werden, bevor weitere Abfragen verarbeitet werden, was einem Datenbanksystem ein allgemeines Gefühl von „Langsamkeit“ verleihen kann. Das Erhöhen von checkpoint_segments oder max_wal_size (abhängig von der Datenbankversion) gibt dem Checkpointer mehr Platz zum Arbeiten und hilft dem Hintergrundschreiber, einen Teil der Schreiblast zu nehmen.

Schritt 4 – Wie ist der Zustand des Hostsystems?

Wenn es in der Datenbank selbst keine Hinweise gibt, ist vielleicht der Host selbst überlastet oder hat Probleme. Alles, von einem überlasteten E/A-Kanal zur Festplatte, überlaufendem Speicher zum Austauschen oder sogar einem ausgefallenen Laufwerk, keines dieser Probleme war bei allem, was wir uns zuvor angesehen haben, offensichtlich. Angenommen, die Datenbank läuft auf einem *nix-basierten Betriebssystem, hier sind ein paar Dinge, die helfen können.

4.1. Systemauslastung

Sehen Sie sich mit „top“ die durchschnittliche Auslastung des Hosts an. Wenn die Anzahl sich der Anzahl der Kerne auf dem System nähert oder sie überschreitet, könnten einfach zu viele gleichzeitige Verbindungen die Datenbank treffen, was sie dazu bringt, aufzuholen.

load average: 3.43, 5.25, 4.85

4.2. Systemspeicher und SWAP

Überprüfen Sie mit „kostenlos“, ob SWAP überhaupt verwendet wurde. Ein Speicherüberlauf zu SWAP in einer PostgreSQL-Datenbankumgebung ist extrem schlecht für die Leistung, und viele DBAs werden SWAP sogar von Datenbankhosts eliminieren, da ein „Speichermangel“-Fehler für viele besser ist als ein träges System.

Wenn SWAP verwendet wird, wird es durch einen Neustart des Systems gelöscht, und es kann angebracht sein, den gesamten Systemspeicher zu erhöhen oder die Speichernutzung für PostgreSQL neu zu konfigurieren (wie z. B. das Verringern von shared_buffers oder work_mem).

[[email protected] ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7986         225        1297          12        6462        7473
Swap:          7987        2048        5939

4.3. Festplattenzugriff

PostgreSQL versucht, einen Großteil seiner Arbeit im Arbeitsspeicher zu erledigen und das Schreiben auf die Festplatte zu verteilen, um Engpässe zu minimieren, aber auf einem überlasteten System mit vielen Schreibvorgängen ist es leicht möglich, dass schwere Lese- und Schreibvorgänge dazu führen, dass das gesamte System langsamer wird, wenn es aufholt auf die Forderungen. Schnellere Festplatten, mehr Festplatten und E/A-Kanäle sind einige Möglichkeiten, die Arbeitsmenge zu erhöhen, die erledigt werden kann.

Tools wie „iostat“ oder „iotop“ können dabei helfen, festzustellen, ob ein Festplattenengpass vorliegt und woher dieser möglicherweise kommt.

4.4. Überprüfen Sie die Protokolle

Wenn alles andere fehlschlägt oder selbst wenn nicht, sollten die Protokolle immer überprüft werden, um festzustellen, ob das System etwas meldet, das nicht stimmt. Wir haben bereits die Überprüfung der postgresql.logs besprochen, aber die Systemprotokolle können Informationen zu Problemen wie fehlerhaften Festplatten, fehlerhaftem Speicher, Netzwerkproblemen usw. enthalten. Jedes dieser Probleme kann dazu führen, dass die Datenbank langsam und unvorhersehbar reagiert, also ein gutes Verständnis von perfekter Gesundheit kann helfen, diese Probleme zu finden.

Laden Sie noch heute das Whitepaper PostgreSQL-Verwaltung und -Automatisierung mit ClusterControl herunterErfahren Sie, was Sie wissen müssen, um PostgreSQL bereitzustellen, zu überwachen, zu verwalten und zu skalierenLaden Sie das Whitepaper herunter

Schritt 5 - Etwas ergibt immer noch keinen Sinn?

Selbst die erfahrensten Administratoren werden auf etwas Neues stoßen, das keinen Sinn ergibt. Hier kann die globale PostgreSQL-Community helfen. Ähnlich wie bei Schritt 0 gilt:Je klarer die Informationen an die Community weitergegeben werden, desto einfacher kann sie helfen.

5.1. PostgreSQL-Mailinglisten

Da PostgreSQL von der Open-Source-Community entwickelt und verwaltet wird, gibt es Tausende von Menschen, die sich in den Mailinglisten austauschen, um unzählige Themen zu diskutieren, darunter Funktionen, Fehler und Leistungsprobleme. Die Mailinglisten finden Sie hier, wobei pgsql-admin und pgsql-performance die wichtigsten sind, wenn Sie Hilfe bei Leistungsproblemen suchen.

5.2. IRC

Freenode hostet mehrere PostgreSQL-Kanäle mit Entwicklern und Administratoren auf der ganzen Welt, und es ist nicht schwer, eine hilfreiche Person zu finden, um herauszufinden, woher Probleme kommen könnten. Weitere Informationen finden Sie auf der PostgreSQL-IRC-Seite.