Sie können Leistungsengpässe ermitteln und Ihre AlloyDB for PostgreSQL-Datenbankvorgänge optimieren, indem Sie Ausführungspläne abrufen und analysieren. Ein Ausführungsplan oder EXPLAIN
-Plan ist eine detaillierte Darstellung der Art und Weise, wie Ihre AlloyDB-Datenbank-Engine eine SQL-Abfrage ausführen möchte. Der Ausführungsplan umfasst einen Baum von Knoten, in dem die Reihenfolge der Vorgänge wie Tabellenscans, Joins, Sortierungen und Aggregationen beschrieben wird, die die AlloyDB-Datenbank zum Abrufen der angeforderten Daten ausführt. Jeder Schritt in diesem Plan wird als Knoten bezeichnet.
Ein Ausführungsplan wird mit dem Befehl EXPLAIN
abgerufen. Dieser gibt den Plan zurück, den der AlloyDB-Abfrageplaner für eine bestimmte SQL-Anweisung generiert. Ein Abfrageplaner, auch als Optimierungstool bezeichnet, ermittelt die effizienteste Methode zum Ausführen einer bestimmten SQL-Abfrage.
Ausführungspläne enthalten die folgenden Komponenten:
- Planknoten: Sie stellen die verschiedenen Schritte bei der Ausführung der Abfrage dar, z. B. einen Scan, einen Join oder einen Sortiervorgang.
- Ausführungszeit: Der EXPLAIN-Plan enthält die geschätzte oder tatsächliche Ausführungszeit für jeden Schritt. So lassen sich Datenbankengpässe ermitteln.
- Pufferverwendung: Hier sehen Sie, wie viele Daten von der Festplatte im Vergleich zum Cache gelesen werden. So lassen sich Probleme beim Lesen von der Festplatte erkennen.
- Parametereinstellungen: Im Plan werden die Parametereinstellungen angezeigt, die während der Ausführung der Abfrage gelten.
PostgreSQL und damit auch AlloyDB unterstützen Ausführungspläne für die folgenden Anweisungen:
SELECT
INSERT
UPDATE
DECLARE CURSOR
CREATE AS
CREATE MATERIALIZED VIEW
REFRESH MATERIALIZED VIEW
EXECUTE
Hinweise
Sie benötigen einen AlloyDB-Cluster und eine AlloyDB-Instanz. Weitere Informationen finden Sie unter Cluster und primäre Instanz erstellen.
Ausführungsplan erstellen
Sie generieren einen Ausführungsplan aus einer Clientanwendung wie psql, pgAdmin oder DBeaver. AlloyDB unterstützt das Generieren von Ausführungsplänen im Text- oder JSON-Format.
So generieren Sie einen Ausführungsplan:
- psql-Client mit einer Instanz verbinden
Führen Sie den folgenden Befehl aus, um einen Ausführungsplan im Textformat zu generieren:
SET enable_ultra_fast_cache_explain_output TO ON; /* AlloyDB Specific Command */ EXPLAIN (analyze, verbose, columnar_engine, costs, settings, buffers, wal, timing, summary, format text)
Führen Sie den folgenden Befehl aus, um einen Ausführungsplan im JSON-Format zu generieren:
SET enable_ultra_fast_cache_explain_output TO ON; /* AlloyDB Specific Command */ EXPLAIN (analyze, verbose, columnar_engine, costs, settings, buffers, wal, timing, summary, format json)
Der Befehl
EXPLAIN
enthält alle verfügbaren Optionen –analyze
,verbose
,columnar_engine
,costs
,settings
,buffers
,wal
,timing
undsummary
–, um einen detaillierten Ausführungsplan für eine bestimmte Abfrage im Text- oder JSON-Format zu generieren. Die Optionanalyze
bedeutet, dass die Abfrage ausgeführt wird, um sowohl tatsächliche Laufzeitstatistiken als auch die Schätzungen des Abfrageplaners zu liefern.
EXPLAIN-Plandaten ansehen und analysieren
Nachdem Sie einen Ausführungsplan erhalten haben, können Sie die Ergebnisse ansehen und analysieren.
Standardmäßig wird in der EXPLAIN
-Ausgabe die serverseitige Abfrageaktivität angezeigt. Um die End-to-End-Roundtrip-Zeit zu messen, verwenden Sie die Option /timing
in psql und speichern Sie die Ergebnisse in /dev/null
.
Um den generierten Ausführungsplan zu sehen, verwenden Sie den Befehl EXPLAIN
vor Ihrer SQL-Abfrage.
EXPLAIN SELECT...
: Hier wird der Plan angezeigt, den der Optimierer ohne Ausführung der Abfrage auswählen würde.EXPLAIN ANALYZE SELECT...
: Führt die Abfrage aus und zeigt sowohl den vorhergesagten Plan als auch die tatsächlichen Ausführungsstatistiken an, einschließlich der tatsächlichen Laufzeiten und Zeilenanzahlen.
ERKLÄRE ohne ANALYSIERE
Wenn Sie die geschätzten Abfragekosten des Abfrageplaners sehen möchten, führen Sie eine EXPLAIN
-Anweisung ohne die Option ANALYZE
aus .
(postgres@10.3.1.17:5432) [postgres] > EXPLAIN select * from public.index_advisor_test;
QUERY PLAN
---------------------------------------------------------------------------------
Seq Scan on index_advisor_test (cost=0.00..1735481.00 rows=100000000 width=27)
AlloyDB query id: 7588555592527881263
AlloyDB plan id: 16134093550604823483
(3 rows)
Die Planausgabe enthält die folgenden Daten:
- cost = 0.00..1735481.00: Die erste Zahl gibt die Kosten für das Abrufen der ersten Zeile an. Die zweite Zahl gibt die Kosten für den Abruf der letzten Zeile an.
- rows = 100000000: Dies ist die geschätzte Anzahl der Zeilen, die von der Abfrage zurückgegeben werden.
- width = 27: Dies ist die geschätzte Breite der zurückgegebenen Zeile. Sie gibt Aufschluss über die aufgerufenen Blöcke.
Option „ANALYSIEREN“
Wenn Sie sowohl die tatsächlichen Ausführungsstatistiken als auch die geschätzten Ausführungsstatistiken sehen möchten, fügen Sie die Option ANALYZE
hinzu.
(postgres@10.3.1.17:5432) [postgres] > EXPLAIN (ANALYZE) select * from public.index_advisor_test;
QUERY PLAN
---------------------------------------------------------------------------------
Seq Scan on index_advisor_test (cost=0.00..1735481.00 rows=100000000 width=27) (actual time=0.165..9342.424 rows=100000001 loops=1)
Planning Time: 0.025 ms
Execution Time: 13674.794 ms
AlloyDB query id: 7588555592527881263
AlloyDB plan id: 16134093550604823483
(5 rows)
Die Planausgabe enthält die folgenden Daten:
- actual time (in ms) = 0.165..9342.424: Hier sehen Sie die tatsächliche Zeit, die benötigt wurde, um die erste Zeile zurückzugeben, und die Gesamtzeit, die benötigt wurde, um alle Zeilen zurückzugeben.
- rows = 100000001: Dies ist die tatsächliche Anzahl der zurückgegebenen Zeilen.
- loops = 1: Dieser Wert ist wichtig für Knoten mit verschachtelten Schleifen. Wenn
loops
größer als 1 ist, wird die durchschnittliche Zeit pro Schleife angezeigt. - Planungszeit: 0,025 ms: Dies gibt die Zeit an, die der Planner benötigt hat, um den Ausführungspfad zu bestimmen.
- Ausführungszeit: 13.674,794 ms: Dies gibt die Zeit an, die für die Ausführung benötigt wurde, nachdem der Planner den Pfad ermittelt hat.
- Gesamtausführungszeit: die Summe aus
Planning Time
undExecution Time
. (0,025 + 13.674,794 = 13.674,819)
Option „VERBOSE“
Mit der Option VERBOSE
können Sie dem Ausführungsplan weitere Informationen hinzufügen. Im folgenden Beispiel werden mit VERBOSE
Schemabeziehungen zu Tabellennamen hinzugefügt und eine interne Abfrage-ID angezeigt, mit der Sie Ihre Abfrage mit anderen Monitoring-Tools in Beziehung setzen können.
(postgres@10.3.1.17:5432) [postgres] > EXPLAIN (ANALYZE,VERBOSE) select * from public.index_advisor_test;
QUERY PLAN
---------------------------------------------------------------------------------
Seq Scan on public.index_advisor_test (cost=0.00..1735481.00 rows=100000000 width=27) (actual time=0.164..6568.938 rows=100000001 loops=1)
Output: id, value, product_id, effective_date
Query Identifier: -5175350694118300766
Planning Time: 0.027 ms
Execution Time: 10875.894 ms
AlloyDB query id: 7588555592527881263
AlloyDB plan id: 16134093550604823483
Die Planausgabe enthält die folgenden Daten:
- Ausgabeknoten: Hier werden die in der Abfrage enthaltenen Spalten aufgeführt. Der Planer enthält manchmal mehr Spalten als angefordert, wenn es teurer wäre, sie wegzulassen.
- Abfrage-ID: Die PostgreSQL-Kennung, die
pg_stat_statements
zugeordnet ist. - AlloyDB-Abfrage-ID: Die AlloyDB-Abfrage-ID, mit der Query Insights-Informationen korreliert werden können.
Option „COLUMNAR ENGINE“
Wenn Sie Informationen zur spaltenbasierten Engine von AlloyDB aufrufen möchten, fügen Sie die Option COLUMNAR_ENGINE
hinzu.
Wenn die Tabelle nicht in der spaltenorientierten Engine vorhanden ist, sehen Sie sich den Status in der Spalte Columnar Check (Spaltenorientierte Prüfung) im folgenden Ausführungsplan an.
(postgres@10.3.1.17:5432) [postgres] > EXPLAIN (ANALYZE,VERBOSE, COLUMNAR_ENGINE) select * from public.index_advisor_test;
QUERY PLAN
---------------------------------------------------------------------------------
Seq Scan on public.index_advisor_test (cost=0.00..1735481.00 rows=100000000 width=27) (actual time=0.009..6328.154 rows=100000001 loops=1)
Output: id, value, product_id, effective_date
Columnar Check: table is not in the columnar store
Query Identifier: -5175350694118300766
Planning Time: 0.027 ms
Execution Time: 10673.310 ms
AlloyDB query id: 7588555592527881263
AlloyDB plan id: 16134093550604823483
Wenn die Tabelle in der spaltenorientierten Engine vorhanden ist und die spaltenorientierte Engine verwendet wird, wird ein benutzerdefinierter Scan zusammen mit Statistiken zur Verwendung der spaltenorientierten Engine angezeigt.
(postgres@10.3.1.17:5432) [postgres] > EXPLAIN (ANALYZE,VERBOSE, COLUMNAR_ENGINE) select * from public.index_advisor_test where product_id = 1;
QUERY PLAN
---------------------------------------------------------------------------------
Append (cost=20.00..27438.78 rows=1166668 width=27) (actual time=0.066..377.029 rows=1000290 loops=1)
-> Custom Scan (columnar scan) on public.index_advisor_test (cost=20.00..27437.66 rows=1166667 width=27) (actual time=0.065..296.904 rows=1000290 loops=1)
Output: id, value, product_id, effective_date
Filter: (index_advisor_test.product_id = 1)
Rows Removed by Columnar Filter: 98999711
Bytes fetched from storage cache: 774835915
Columnar cache search mode: native
Swap-in Time: 92.708 ms
-> Seq Scan on public.index_advisor_test (cost=0.00..1.11 rows=1 width=27) (never executed)
Output: id, value, product_id, effective_date
Filter: (index_advisor_test.product_id = 1)
Query Identifier: -4660018746142248761
Planning Time: 0.217 ms
Execution Time: 421.114 ms
AlloyDB query id: 13855683355620344431
AlloyDB plan id: 2126918133221480510
Die Planausgabe enthält die folgenden Daten:
- Abfragefilter (Prädikat): Hier wird der angewendete Filter angezeigt, sofern Sie einen verwenden.
- Durch Spaltenfilter entfernte Zeilen: Gibt die Anzahl der Zeilen an, die durch den Spaltenfilter entfernt wurden.
- Aus Speichercache abgerufene Byte: Hier sehen Sie die Anzahl der Byte, die aus dem Speichercache abgerufen wurden.
- Swap-in Time (Zeit für das Einlagern): Die Zeit, die erforderlich ist, um Daten aus dem spaltenweisen Spill-Cache (SSD) zu tauschen, wenn die Beziehung nicht in den Arbeitsspeicher passt.
Option „EINSTELLUNGEN“
Wenn Sie nicht standardmäßige Sitzungs-, Datenbank- oder globale Einstellungen sehen möchten, die vom Planner verwendet werden, fügen Sie die Option SETTINGS
hinzu.
(postgres@10.3.1.17:5432) [postgres] > EXPLAIN (ANALYZE,VERBOSE, COLUMNAR_ENGINE,COSTS,SETTINGS) select * from public.index_advisor_test;
QUERY PLAN
---------------------------------------------------------------------------------
Seq Scan on public.index_advisor_test (cost=0.00..1735481.00 rows=100000000 width=27) (actual time=0.007..6366.249 rows=100000001 loops=1)
Output: id, value, product_id, effective_date
Columnar Check: table is not in the columnar store
Settings: effective_cache_size = '19690120kB', random_page_cost = '1.1', work_mem = '256MB'
Query Identifier: -5175350694118300766
Planning Time: 0.027 ms
Execution Time: 10727.068 ms
AlloyDB query id: 7588555592527881263
AlloyDB plan id: 16134093550604823483
Option „BUFFERS“
Verwenden Sie das Keyword BUFFERS
, um Informationen zur Datenquelle aufzurufen. Die Anzahl der BUFFERS
wird über alle Schritte hinweg kumuliert, nicht nur für einen bestimmten Schritt im Plan.
(postgres@10.3.1.17:5432) [postgres] > EXPLAIN (ANALYZE,VERBOSE, COLUMNAR_ENGINE,COSTS,SETTINGS, BUFFERS) select * from public.effective_io_concurrency_test;
QUERY PLAN
---------------------------------------------------------------------------------
Seq Scan on public.effective_io_concurrency_test (cost=0.00..1844356.96 rows=100058296 width=31) (actual time=0.111..10007.193 rows=100000001 loops=1)
Output: id, value, product_id, effective_date
Buffers: shared hit=1185 read=842625 dirtied=1, ultra fast cache hit=842625
I/O Timings: shared read=2588.597
Columnar Check: table is not in the columnar store
Settings: effective_cache_size = '19690120kB', random_page_cost = '1.1', work_mem = '256MB'
Query Identifier: -5987221491374921441
Planning:
Buffers: shared hit=58 read=2, ultra fast cache hit=2
I/O Timings: shared read=0.215
Planning Time: 0.410 ms
Execution Time: 14825.271 ms
AlloyDB query id: 12754549874439071326
AlloyDB plan id: 13656575252012920931
Die Pufferinformationen umfassen Folgendes:
- Gemeinsamer Treffer: Die Anzahl der 8-KB-Datenblöcke, die im Haupt-Cache für freigegebene Puffer von PostgreSQL gefunden wurden.
- shared read (gemeinsames Lesen): Die Anzahl der 8-KB-Datenblöcke, die vom Betriebssystem gelesen wurden. Das weist oft auf Laufwerks-E/A hin.
- dirtied: Die Anzahl der zuvor unveränderten Blöcke, die durch die Abfrage geändert wurden (Änderungen an der Sichtbarkeitskarte).
- written: Die Anzahl der zuvor geänderten Blöcke, die von diesem Backend während der Abfrageverarbeitung aus dem Cache entfernt wurden, in der Regel aufgrund von Änderungen am Hinweisbit oder an der Sichtbarkeitsübersicht, und auf die Festplatte geschrieben wurden.
- Treffer im ultraschnellen Cache: Anzahl der Blöcke, die aus dem ultraschnellen Cache abgerufen wurden.
- E/A-Zeitangaben: Die Dauer von Festplatten- oder SSD-E/A-Vorgängen in Millisekunden.
- Planung: Pufferaktivität während der Planungsphase, z. B. das Lesen von Metadaten oder Statistiken aus Katalogtabellen.
- Für E/A während der Planung aufgewendete Zeit: Hier wird die E/A-Zeit angezeigt, wenn Metadaten vom Laufwerk gelesen werden mussten.
WAL-Option
Wenn Sie Informationen zu Write-Ahead Logging-Aktivitäten (WAL) bereitstellen möchten, verwenden Sie die Option WAL
.
(postgres@10.3.1.17:5432) [postgres] > EXPLAIN (ANALYZE,VERBOSE, COLUMNAR_ENGINE,COSTS,SETTINGS, BUFFERS, WAL) select * from public.effective_io_concurrency_test;
QUERY PLAN
---------------------------------------------------------------------------------
Seq Scan on public.effective_io_concurrency_test (cost=0.00..1844356.96 rows=100058296 width=31) (actual time=0.010..10147.314 rows=100000001 loops=1)
Output: id, value, product_id, effective_date
Buffers: shared hit=1185 read=842625 dirtied=1, ultra fast cache hit=842625
I/O Timings: shared read=2590.410
WAL: records=18 bytes=5178
Columnar Check: table is not in the columnar store
Settings: effective_cache_size = '19690120kB', random_page_cost = '1.1', work_mem = '256MB'
Query Identifier: -5987221491374921441
Planning Time: 0.030 ms
Execution Time: 15033.004 ms
AlloyDB query id: 12754549874439071326
AlloyDB plan id: 13656575252012920931
Die WAL-Informationen umfassen Folgendes:
- WAL-Einträge: Die Anzahl der gelesenen WAL-Einträge, um die Konsistenz aufrechtzuerhalten.
- WAL-Byte: Anzahl der Byte, die aus dem WAL gelesen wurden, um die Konsistenz aufrechtzuerhalten.
- Einträge, die geändert, aber noch nicht checkpointed wurden: Dies weist auf Einträge hin, die geändert, aber noch nicht checkpointed wurden.