Eine klassische Frage, die Entwickler an ihren DBA oder GeschĂ€ftsinhaber â an einen PostgreSQL-Berater â stellen, lautet fast immer gleich: âWarum dauern die Abfragen auf der Datenbank so lange?â
Eine traditionelle Reihe von GrĂŒnden:
- ineffizienter Algorithmus
wenn Sie beschlossen haben, mehrere CTEs mit mehreren Zehntausend DatensĂ€tzen zu verknĂŒpfen - veraltete Statistiken.
wenn die tatsĂ€chliche Verteilung der Daten in der Tabelle bereits stark von der zuletzt durchgefĂŒhrten ANALYSE abweicht - "Engpass" bei den Ressourcen
und es an den zugewiesenen CPU-Ressourcen mangelt, Gigabytes an Speicher stĂ€ndig voll ausgelastet sind oder die Festplatte den vielen âWĂŒnschenâ der DB nicht gerecht wird - Sperrung wegen konkurrierender Prozesse
Und wenn Sperren schwer zu erfassen und zu analysieren sind, dann genĂŒgt uns fĂŒr alles andere der Abfrageplan, den man mit Hilfe von (am besten direkt EXPLAIN (ANALYZE, BUFFERS) ...) oder .
Aber, wie in der betreffenden Dokumentation erwÀhnt,
âDas VerstĂ€ndnis des Plans ist eine Kunst, und um diese zu meistern, benötigt man eine gewisse Erfahrung ...â
Aber man kann auch ohne diese auskommen, wenn man ein geeignetes Werkzeug verwendet!
Wie sieht ein Anfrageplan normalerweise aus? So etwa:
Index Scannen ĂŒber pg_class_relname_nsp_index auf pg_class (tatsĂ€chliche Zeit=0.049..0.050 Zeilen=1 Schleifen=1)
Index Bedingung: (relname = $1)
Filter: (oid = $0)
Puffer: gemeinsamer Treffer=4
InitPlan 1 (gibt $0,$1 zurĂŒck)
-> Limit (tatsÀchliche Zeit=0.019..0.020 Zeilen=1 Schleifen=1)
Puffer: gemeinsamer Treffer=1
-> Seq Scannen auf pg_class pg_class_1 (tatsÀchliche Zeit=0.015..0.015 Zeilen=1 Schleifen=1)
Filter: (relkind = 'r'::"char")
Entfernte Zeilen durch Filter: 5
Puffer: gemeinsamer Treffer=1oder so:
"Append (Kosten=868.60..878.95 Zeilen=2 Breite=233) (tatsÀchliche Zeit=0.024..0.144 Zeilen=2 Schleifen=1)"
" Puffer: gemeinsamer Treffer=3"
" CTE cl"
" -> Seq Scannen auf pg_class (Kosten=0.00..868.60 Zeilen=9972 Breite=537) (tatsÀchliche Zeit=0.016..0.042 Zeilen=101 Schleifen=1)"
" Puffer: gemeinsamer Treffer=3"
" -> Limit (Kosten=0.00..0.10 Zeilen=1 Breite=233) (tatsÀchliche Zeit=0.023..0.024 Zeilen=1 Schleifen=1)"
" Puffer: gemeinsamer Treffer=1"
" -> CTE Scannen auf cl (Kosten=0.00..997.20 Zeilen=9972 Breite=233) (tatsÀchliche Zeit=0.021..0.021 Zeilen=1 Schleifen=1)"
" Puffer: gemeinsamer Treffer=1"
" -> Limit (Kosten=10.00..10.10 Zeilen=1 Breite=233) (tatsÀchliche Zeit=0.117..0.118 Zeilen=1 Schleifen=1)"
" Puffer: gemeinsamer Treffer=2"
" -> CTE Scannen auf cl cl_1 (Kosten=0.00..997.20 Zeilen=9972 Breite=233) (tatsÀchliche Zeit=0.001..0.104 Zeilen=101 Schleifen=1)"
" Puffer: gemeinsamer Treffer=2"
"Planungszeit: 0.634 ms"
"AusfĂŒhrungszeit: 0.248 ms"Aber den Plan als Text »von der Liste« zu lesen, ist sehr schwierig und unĂŒbersichtlich:
- im Knoten wird ausgegeben die Summe der Ressourcen des Teilbaums
Das bedeutet, um zu verstehen, wie viel Zeit fĂŒr die AusfĂŒhrung eines bestimmten Knotens aufgewendet wurde oder wie genau dieses Lesen der Daten aus der Tabelle von der Festplatte abgerufen wurde â muss man irgendwie das Eine vom Anderen abziehen. - Die Knotenzeit ist erforderlich. Multiplizieren mit loops.
Ja, Subtraktion ist noch nicht die komplizierteste Operation, die man âim Kopfâ durchfĂŒhren muss â schlieĂlich wird die AusfĂŒhrungszeit als Durchschnitt fĂŒr einen einzelnen Knoten angegeben, und es können Hunderte von ihnen vorhanden sein. - Nun, all das zusammen erschwert die Antwort auf die Hauptfrage â also, wer ist das âschwĂ€chste Gliedâ??
Als wir versuchten, all dies mehreren Hundert unserer Entwickler zu erklĂ€ren, stellten wir fest, dass das von auĂen etwa so aussieht:

Ah, das heiĂt, wir brauchenâŠ
Ein Tool
In diesem haben wir versucht, alle SchlĂŒsselmechaniken zu sammeln, die helfen, anhand des Plans und der Anfrage zu verstehen, âwer schuld ist und was zu tun istâ. Und auĂerdem wollten wir einen Teil unseres Wissens mit der Gemeinschaft teilen.
Treffen Sie und nutzen Sie â
Anschaulichkeit der PlÀne
Ist es leicht, den Plan zu verstehen, wenn er so aussieht?
Seq Scan on pg_class (tatsÀchliche Zeit=0.009..1.304 Zeilen=6609 Schleifen=1)
Buffer: shared hit=263
Planungszeit: 0,108 ms
AusfĂŒhrungszeit: 1,800 ms
Nicht wirklich.
Aber so, in verkĂŒrzter Form, wenn die SchlĂŒsselindikatoren getrennt sind â ist es bereits viel klarer:

Aber wenn der Plan komplexer ist, kommt Hilfe von Kreisdiagramm der Zeitverteilung nach Knoten:

FĂŒr die kompliziertesten Varianten steht uns auch die AusfĂŒhrungsdiagramm:

Es gibt tatsÀchlich Nicht-Trivial-FÀlle, in denen ein Plan mehr als eine tatsÀchliche Wurzel haben kann:


Strukturelle Hinweise
Wenn die gesamte Struktur des Plans und dessen Schwachstellen bereits aufgegliedert und sichtbar sind, warum dann nicht dem Entwickler markieren und «in verstÀndlicher Sprache» erklÀren?
Solcher Empfehlungsvorlagen haben wir bereits einige Dutzend gesammelt.
Zeilenprofilierer der Anfrage
Wenn wir nun den analysierten Plan mit der ursprĂŒnglichen Anfrage kombinieren, können wir sehen, wie viel Zeit jeder einzelne Operator in Anspruch genommen hat â etwa so:

⊠oder sogar so:

Parameterersetzung in der Anfrage
Wenn Sie nicht nur die Anfrage, sondern auch deren Parameter aus der DETAIL-Zeile des Logs an den Plan angehÀngt haben, können Sie ihn in einer der Varianten zusÀtzlich kopieren:
- mit den Werten in der Anfrage ersetzt
zum unmittelbaren AusfĂŒhren auf Ihrer Datenbank und zur weiteren ProfilierungSELECT 'const', 'param'::text; - mit den Werten ĂŒber PREPARE/EXECUTE ersetzt
fĂŒr die Simulation der Arbeitsweise des Planers, wenn der parametrische Teil ignoriert werden kann â zum Beispiel bei der Arbeit mit partitionierten TabellenDEALLOCATE ALL; PREPARE q(text) AS SELECT 'const', $1::text; EXECUTE q('param'::text);
Planarchive
FĂŒgen Sie hinzu, analysieren Sie, teilen Sie mit Kollegen! Die PlĂ€ne bleiben im Archiv, und Sie können spĂ€ter darauf zurĂŒckgreifen:
Wenn Sie jedoch nicht möchten, dass Ihr Plan von anderen gesehen wird, vergessen Sie nicht, das KÀstchen "nicht im Archiv veröffentlichen" anzukreuzen.
In den kommenden Artikeln werde ich ĂŒber die Herausforderungen und Lösungen sprechen, die bei der Analyse von PlĂ€nen auftreten.
Quelle: habr.com
