Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

Vor einem halben Jahr haben wir vorgestellt explain.tensor.ru — ein öffentlicher Dienst zur Analyse und Visualisierung von AbfrageplĂ€nen fĂŒr PostgreSQL.

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

In den vergangenen Monaten haben wir einen Bericht darĂŒber erstellt ĂŒber PGConf.Russia 2020, eine zusammenfassende Artikel zur Beschleunigung von SQL-Abfragen vorbereitet basierend auf den Empfehlungen, die er ausgibt
 aber das Wichtigste ist, dass wir Ihr Feedback gesammelt und die realen AnwendungsfĂ€lle beobachtet haben.

Und jetzt sind wir bereit, ĂŒber die neuen Möglichkeiten zu berichten, die Sie nutzen können.

UnterstĂŒtzung verschiedener Planformate

Plan aus dem Log, zusammen mit der Abfrage

Markieren Sie direkt in der Konsole den gesamten Block, beginnend mit der Zeile mit Query Text, mit allen fĂŒhrenden Leerzeichen:

        Query Text: INSERT INTO dicquery_20200604 VALUES ($1.*) ON CONFLICT (query)
                           DO NOTHING;
        Insert on dicquery_20200604 (cost=0.00..0.05 rows=1 width=52) (actual time=40.376..40.376 rows=0 loops=1)
          Conflict Resolution: NOTHING
          Conflict Arbiter Indexes: dicquery_20200604_pkey
          Tuples Inserted: 1
          Conflicting Tuples: 0
          Buffers: shared hit=9 read=1 dirtied=1
          -> Result (cost=0.00..0.05 rows=1 width=52) (actual time=0.001..0.001 rows=1 loops=1)


 und fĂŒgen alles, was wir kopiert haben, direkt in das Feld fĂŒr den Plan ein, ohne etwas zu teilen:

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

Am Ende erhalten wir zusĂ€tzlich zum erlĂ€uterten Plan noch den Reiter „Kontext“, wo unsere Anfrage in vollem Glanz prĂ€sentiert wird:

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

JSON und YAML

EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT * FROM pg_class;

"[
  {
    "Plan": {
      "Node Type": "Seq Scan",
      "Parallel Aware": false,
      "Relation Name": "pg_class",
      "Alias": "pg_class",
      "Startup Cost": 0.00,
      "Total Cost": 1336.20,
      "Plan Rows": 13804,
      "Plan Width": 539,
      "Actual Startup Time": 0.006,
      "Actual Total Time": 1.838,
      "Actual Rows": 10266,
      "Actual Loops": 1,
      "Shared Hit Blocks": 646,
      "Shared Read Blocks": 0,
      "Shared Dirtied Blocks": 0,
      "Shared Written Blocks": 0,
      "Local Hit Blocks": 0,
      "Local Read Blocks": 0,
      "Local Dirtied Blocks": 0,
      "Local Written Blocks": 0,
      "Temp Read Blocks": 0,
      "Temp Written Blocks": 0
    },
    "Planning Time": 5.135,
    "Triggers": [
    ],
    "Execution Time": 2.389
  }
]"

Ob mit Ă€ußeren AnfĂŒhrungszeichen, wie es pgAdmin kopiert, oder ohne – werfen wir es in dasselbe Feld, am Ende – Schönheit:

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

Erweiterte Visualisierung

Planungszeit / AusfĂŒhrungszeit

Jetzt sieht man besser, wo die zusĂ€tzliche Zeit bei der AusfĂŒhrung der Abfrage geblieben ist:

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

I/O-Zeit

Manchmal muss man mit der Situation umgehen, dass im Plan anscheinend nicht zu viele Ressourcen gelesen oder geschrieben wurden, aber die AusfĂŒhrungszeit irgendwie unverhĂ€ltnismĂ€ĂŸig groß ist.

Hier muss man sagen: "Oh, wahrscheinlich war der Server in diesem Moment zu stark ausgelastet, deshalb dauerte das Lesen so lange!" Aber irgendwie ist das nicht sehr genau


Aber man kann das absolut zuverlÀssig feststellen. Es liegt daran, dass unter den Konfigurationsoptionen des PG-Servers track_io_timing:

Erfasst die Zeit fĂŒr Ein- und Ausgabeoperationen. Dieser Parameter ist standardmĂ€ĂŸig deaktiviert, da es erforderlich ist, stĂ€ndig die aktuelle Zeit vom Betriebssystem abzufragen, was die Leistung auf einigen Plattformen erheblich verlangsamen kann. Um die Kosten der Zeitmessung auf Ihrer Plattform zu bewerten, können Sie das Dienstprogramm pg_test_timing verwenden. Die Ein-/Ausgabe-Statistiken können ĂŒber die Ansicht pg_stat_database abgerufen werden, im EXPLAIN-Ausgabe (wenn der Parameter BUFFERS verwendet wird) und ĂŒber die Ansicht pg_stat_statements.

Dieser Parameter kann auch innerhalb einer lokalen Sitzung aktiviert werden:

SET track_io_timing = TRUE;

Nun, das angenehmste — wir haben gelernt, diese Daten zu verstehen und anzuzeigen, unter BerĂŒcksichtigung aller Transformationen des AusfĂŒhrungsbaums:

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

Hier kann man beobachten, dass von 0,790 ms der gesamten AusfĂŒhrungszeit 0,718 ms fĂŒr das Lesen einer Seite von Daten benötig wurden, 0,044 ms fĂŒr das Schreiben derselben und fĂŒr alle anderen nĂŒtzlichen AktivitĂ€ten insgesamt nur 0,028 ms aufgewendet wurden!

Die Zukunft mit PostgreSQL 13

Eine vollstĂ€ndige Übersicht ĂŒber die Neuerungen finden Sie in einem ausfĂŒhrlichen Artikel, wĂ€hrend wir spezifisch ĂŒber die Änderungen in der Planung sprechen.

Planung der Puffer

Die BerĂŒcksichtigung der Ressourcen, die dem Planner zugewiesen sind, spiegelt sich auch in einem anderen Patch wider, der nicht zu pg_stat_statements gehört. EXPLAIN mit der Option BUFFERS wird die Anzahl der Puffer melden, die in der Planungsphase verwendet wurden:

 Seq Scan auf pg_class (tatsÀchliche Zeilen=386 Schleifen=1)
   Puffer: gemeinsam Treffer=9 gelesen=4
 Planungszeit: 0.782 ms
   Puffer: gemeinsam Treffer=103 gelesen=11
 AusfĂŒhrungszeit: 0.219 ms

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

Inkrementelle Sortierung

In FĂ€llen, in denen eine Sortierung nach vielen SchlĂŒsseln erforderlich ist (k1, k2, k3
), kann der Planner nun das Wissen nutzen, dass die Daten bereits nach einigen der ersten SchlĂŒssel (z. B. k1 und k2) sortiert sind. In diesem Fall mĂŒssen die gesamten Daten nicht erneut sortiert werden, sondern sie können in aufeinanderfolgende Gruppen mit gleichen Werten fĂŒr k1 und k2 unterteilt und nach dem SchlĂŒssel k3 "nachsortiert" werden.

So zerfĂ€llt die gesamte Sortierung in mehrere aufeinanderfolgende Sortierungen kleinerer GrĂ¶ĂŸe. Dies reduziert den benötigten Speicherbedarf und ermöglicht es zudem, die ersten Daten frĂŒher auszugeben, bevor die gesamte Sortierung vollstĂ€ndig abgeschlossen ist.

 Inkrementelle Sortierung (tatsÀchliche Zeilen=2949857 Schleifen=1)
   SortierschlĂŒssel: ticket_no, passenger_id
   Vorgesortierter SchlĂŒssel: ticket_no
   Vollsortiergruppen: 92184 Sortiermethode: Quicksort Speicher: avg=31kB peak=31kB
   ->  Indexpfadsuche mit tickets_pkey auf tickets (tatsÀchliche Zeilen=2949857 Schleifen=1)
 Planungszeit: 2.137 ms
 AusfĂŒhrungszeit: 2230.019 ms

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser
Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

Verbesserungen UI/UX

Screenshots, sie sind ĂŒberall!

Jetzt gibt es auf jedem Tab die Möglichkeit, schnell einen Screenshot des Tabs in die Zwischenablage zu ĂŒbernehmen in voller Breite und Tiefe des Tabs – das „Fadenkreuz“ oben rechts:

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

Die meisten Bilder fĂŒr diese Veröffentlichung wurden tatsĂ€chlich auf diese Weise erhalten.

Empfehlungen in den Knoten

Es sind nicht nur mehr geworden, sondern man kann auch ĂŒber jeden einzelnen detailliert im Artikel lesen, indem man dem Link folgt:

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

Löschen aus dem Archiv

Einige haben dringend gebeten, die Möglichkeit hinzuzufĂŒgen, „vollstĂ€ndig“ zu löschen auch nicht veröffentlichte PlĂ€ne im Archiv – bitte, es genĂŒgt, das entsprechende Symbol zu drĂŒcken:

Wir verstehen die PlÀne von PostgreSQL-Abfragen noch besser

Nun, und vergessen wir nicht, dass wir eine Supportgruppe haben,, an die man seine Anmerkungen und VorschlÀge schreiben kann.

Quelle: habr.com

60GB SSD 8Gb DDR4