Was erklärt mir PostgreSQL genau?

116

Die Erklärungsausgabe von MySQL ist ziemlich einfach. PostgreSQL ist etwas komplizierter. Ich konnte auch keine gute Ressource finden, die dies erklärt.

Können Sie beschreiben, was genau zu erklären ist, oder mich zumindest in Richtung einer guten Ressource weisen?

kjg
quelle

Antworten:

50

Explaining_EXPLAIN.pdf könnte ebenfalls helfen.

Milen A. Radev
quelle
64
Ich bin verwirrt, warum die Leute denken, dass Dia-Decks eine gute technische Dokumentation sind. Ein Video des Vortrags mag hilfreich sein, aber die Informationsdichte dieses Dia-Decks liegt sehr nahe bei Null. In den ersten sechs Folien (1/5 der Gesamtzahl) gibt es genau 1 Satz technischen Inhalts: "• EXPLAIN funktioniert mit jeder DML, nicht nur mit SELECT (dh UPDATE, DELETE und INSERT)." Mein größtes Missverständnis ist, was "Startzeit" bedeutet, und das wird in diesen ~ 30 Folien nirgends erklärt.
Mark E. Haase
80

Der Teil, den ich immer verwirrend fand, sind die Startkosten im Vergleich zu den Gesamtkosten. Ich google dies jedes Mal, wenn ich es vergesse, was mich hierher zurückbringt, was den Unterschied nicht erklärt, weshalb ich diese Antwort schreibe. Dies habe ich aus der Postgres- EXPLAINDokumentation entnommen , die so erklärt wurde, wie ich sie verstehe.

Hier ist ein Beispiel aus einer Anwendung, die ein Forum verwaltet:

EXPLAIN SELECT * FROM post LIMIT 50;

Limit  (cost=0.00..3.39 rows=50 width=422)
  ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

Hier ist die grafische Erklärung von PgAdmin:

grafische Erklärung der ersten Abfrage

(Wenn Sie PgAdmin verwenden, können Sie mit der Maus auf eine Komponente zeigen, um die Kostendetails zu lesen.)

Die Kosten werden als Tupel dargestellt wird , zum Beispiel die Kosten der LIMITist cost=0.00..3.39und die Kosten des sequenziellen Abtastung postist cost=0.00..15629.12. Die erste Zahl im Tupel sind die Startkosten und die zweite Zahl sind die Gesamtkosten . Da ich verwendet habe EXPLAINund nicht EXPLAIN ANALYZE, sind diese Kosten Schätzungen, keine tatsächlichen Maßnahmen.

  • Startkosten sind ein kniffliges Konzept. Es gibt nicht nur die Zeit an, die diese Komponente startet . Es gibt die Zeitspanne zwischen dem Start der Komponente (Einlesen von Daten) und der Ausgabe der ersten Zeile durch die Komponente an .
  • Die Gesamtkosten sind die gesamte Ausführungszeit der Komponente, vom Beginn des Einlesens der Daten bis zum Abschluss des Schreibens der Ausgabe.

Als Komplikation umfassen die Kosten jedes "übergeordneten" Knotens die Kosten seiner untergeordneten Knoten. In der Textdarstellung wird der Baum durch Einrückung dargestellt, z. B. LIMITist er ein übergeordneter Knoten und Seq Scansein untergeordnetes Element . In der PgAdmin-Darstellung zeigen die Pfeile von Kind zu Elternteil - die Richtung des Datenflusses -, was möglicherweise nicht intuitiv ist, wenn Sie mit der Graphentheorie vertraut sind.

In der Dokumentation heißt es, dass die Kosten alle untergeordneten Knoten einschließen. Beachten Sie jedoch, dass die Gesamtkosten des übergeordneten 3.39Knotens viel geringer sind als die Gesamtkosten des untergeordneten Knotens 15629.12. Die Gesamtkosten sind nicht inklusive, da eine Komponente wie LIMITdiese nicht ihre gesamte Eingabe verarbeiten muss. Siehe das EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2;Beispiel in der Postgres- EXPLAINDokumentation .

Im obigen Beispiel ist die Startzeit für beide Komponenten Null, da keine Komponente eine Verarbeitung durchführen muss, bevor sie mit dem Schreiben von Zeilen beginnt: Ein sequentieller Scan liest die erste Zeile der Tabelle und gibt sie aus. Der LIMITliest seine erste Zeile und gibt sie dann aus.

Wann müsste eine Komponente viel verarbeiten, bevor sie Zeilen ausgeben kann? Es gibt viele mögliche Gründe, aber schauen wir uns ein klares Beispiel an. Hier ist dieselbe Abfrage wie zuvor, die jetzt eine ORDER BYKlausel enthält:

EXPLAIN SELECT * FROM post ORDER BY body LIMIT 50;

Limit  (cost=23283.24..23283.37 rows=50 width=422)
  ->  Sort  (cost=23283.24..23859.27 rows=230412 width=422)
        Sort Key: body
        ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

Und grafisch:

grafische Erklärung der zweiten Abfrage

Auch hier hat der sequentielle Scan postkeine Startkosten: Er beginnt sofort mit der Ausgabe von Zeilen. Die Sortierung hat jedoch erhebliche Startkosten, 23283.24da die gesamte Tabelle sortiert werden muss, bevor auch nur eine einzelne Zeile ausgegeben werden kann . Die Gesamtkosten der Sortierung 23859.27sind nur geringfügig höher als die Startkosten. Dies spiegelt die Tatsache wider, dass die sortierten Daten nach dem Sortieren des gesamten Datensatzes sehr schnell ausgegeben werden können.

Beachten Sie, dass die Startzeit von LIMIT 23283.24genau der Startzeit der Sortierung entspricht. Dies liegt nicht daran, dass LIMITselbst eine hohe Startzeit vorliegt. Es hat für sich genommen keine Startzeit von Null, fasst jedoch EXPLAINalle untergeordneten Kosten für jeden Elternteil zusammen, sodass die LIMITStartzeit die Summe der Startzeiten seiner untergeordneten Elemente enthält.

Dieser Kostenaufschlag kann es schwierig machen, die Ausführungskosten jeder einzelnen Komponente zu verstehen. Zum Beispiel hat unsere LIMITkeine Startzeit, aber das ist auf den ersten Blick nicht offensichtlich. Aus diesem Grund haben mehrere andere Personen auf EXPLAIN.depesz.com verlinkt , ein von Hubert Lubaczewski (auch bekannt als depesz) entwickeltes Tool, das das Verständnis erleichtert, EXPLAINindem es unter anderem die Kinderkosten von den Elternkosten abzieht. In einem kurzen Blogbeitrag über sein Tool erwähnt er einige andere Komplexitäten .

Mark E. Haase
quelle
4
Danke dafür. Ich möchte auch einen EXPLAIN-Visualizer hinzufügen, der die Ausgabe (imo) noch besser anzeigt. tatiyants.com/pev
Jonathan Porter
Gute Antwort. Und Ihr Kommentar, dass die Startkosten die Zeit bis zur Rückgabe der ersten Zeile enthalten, hat mir geholfen zu verstehen, warum die Startkosten für die Sortierung nicht nur 15629.12 waren.
Joel Wigton
43

Es wird von am meisten eingerückt bis am wenigsten eingerückt ausgeführt, und ich glaube vom unteren Ende des Plans bis zum oberen Rand. (Wenn es also zwei eingerückte Abschnitte gibt, wird der eine weiter unten auf der Seite zuerst ausgeführt. Wenn sie den anderen treffen, wird die Regel ausgeführt, die sie verbindet.)

Die Idee ist, dass bei jedem Schritt 1 oder 2 Datensätze eintreffen und von einer Regel verarbeitet werden. Wenn nur ein Datensatz vorhanden ist, wird diese Operation für diesen Datensatz ausgeführt. (Scannen Sie beispielsweise einen Index, um herauszufinden, welche Zeilen Sie möchten, filtern Sie ein Dataset oder sortieren Sie es.) Wenn zwei, sind die beiden Datasets die beiden Dinge, die weiter eingerückt sind, und sie werden durch die angezeigte Regel verbunden. Die Bedeutung der meisten Regeln kann relativ leicht erraten werden (insbesondere, wenn Sie zuvor eine Reihe von Erklärungsplänen gelesen haben). Sie können jedoch versuchen, einzelne Elemente zu überprüfen, indem Sie entweder in der Dokumentation nachsehen oder (einfacher), indem Sie einfach den Satz hineinwerfen Google zusammen mit ein paar Keywords wie EXPLAIN.

Dies ist offensichtlich keine vollständige Erklärung, bietet jedoch genügend Kontext, sodass Sie normalerweise herausfinden können, was Sie wollen. Betrachten Sie diesen Plan beispielsweise aus einer tatsächlichen Datenbank:

explain analyze
select a.attributeid, a.attributevalue, b.productid
from orderitemattribute a, orderitem b
where a.orderid = b.orderid
and a.attributeid = 'display-album'
and b.productid = 'ModernBook';

------------------------------------------------------------------------------------------------------------------------------------------------------------

 Merge Join  (cost=125379.14..125775.12 rows=3311 width=29) (actual time=841.478..841.478 rows=0 loops=1)
   Merge Cond: (a.orderid = b.orderid)
   ->  Sort  (cost=109737.32..109881.89 rows=57828 width=23) (actual time=736.163..774.475 rows=16815 loops=1)
         Sort Key: a.orderid
         Sort Method:  quicksort  Memory: 1695kB
         ->  Bitmap Heap Scan on orderitemattribute a  (cost=1286.88..105163.27 rows=57828 width=23) (actual time=41.536..612.731 rows=16815 loops=1)
               Recheck Cond: ((attributeid)::text = 'display-album'::text)
               ->  Bitmap Index Scan on (cost=0.00..1272.43 rows=57828 width=0) (actual time=25.033..25.033 rows=16815 loops=1)
                     Index Cond: ((attributeid)::text = 'display-album'::text)
   ->  Sort  (cost=15641.81..15678.73 rows=14769 width=14) (actual time=14.471..16.898 rows=1109 loops=1)
         Sort Key: b.orderid
         Sort Method:  quicksort  Memory: 76kB
         ->  Bitmap Heap Scan on orderitem b  (cost=310.96..14619.03 rows=14769 width=14) (actual time=1.865..8.480 rows=1114 loops=1)
               Recheck Cond: ((productid)::text = 'ModernBook'::text)
               ->  Bitmap Index Scan on id_orderitem_productid  (cost=0.00..307.27 rows=14769 width=0) (actual time=1.431..1.431 rows=1114 loops=1)
                     Index Cond: ((productid)::text = 'ModernBook'::text)
 Total runtime: 842.134 ms
(17 rows)

Lesen Sie es selbst und prüfen Sie, ob es sinnvoll ist.

Was ich gelesen habe, ist, dass die Datenbank zuerst den id_orderitem_productidIndex scannt , anhand dessen die gewünschten Zeilen gefunden werden orderitem, dann das Dataset mithilfe eines Quicksorts sortiert wird (die verwendete Sortierung ändert sich, wenn die Daten nicht in den RAM passen) und diese dann beiseite legt.

Als Nächstes wird orditematt_attributeid_idxnach den gewünschten Zeilen gesucht orderitemattributeund das Dataset mithilfe eines Quicksorts sortiert.

Anschließend werden die beiden Datensätze verwendet und zusammengeführt. (Ein Merge-Join ist eine Art "Zipping" -Operation, bei der die beiden sortierten Datasets parallel durchlaufen werden und die verknüpfte Zeile ausgegeben wird, wenn sie übereinstimmen.)

Wie gesagt, Sie arbeiten den Plan von innen nach außen, von unten nach oben durch.

user11318
quelle
22

Es gibt auch ein Online- Hilfstool , Depesz , das hervorhebt, wo sich die teuren Teile der Analyseergebnisse befinden.

hat auch eines, hier sind die gleichen Ergebnisse , die mir klarer machen, wo das Problem liegt.

Stephen Denne
quelle
20
EXPLAIN-analyze.info scheint nicht verfügbar zu sein, aber ich stimme zu, dass EXPLAIN.DEPESZ.com sehr hilfreich ist.
BenvolioT
13

PgAdmin zeigt Ihnen eine grafische Darstellung des Erklärungsplans. Das Hin- und Herwechseln zwischen den beiden kann Ihnen wirklich helfen, die Bedeutung der Textdarstellung zu verstehen. Wenn Sie jedoch nur wissen möchten, was zu tun ist, können Sie möglicherweise immer die GUI verwenden.

Grant Johnson
quelle
0

Wenn Sie pgadmin installieren, gibt es eine Schaltfläche "Erklären", mit der Sie neben der Textausgabe auch Diagramme des Geschehens zeichnen und die Filter, Sortierungen und Zusammenstellungen von Teilmengen anzeigen können, die ich für sehr nützlich halte, um zu sehen, was passiert.

Greg
quelle