Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
Aurora DSQL EXPLAIN-Pläne lesen
Zu verstehen, wie man EXPLAIN-Pläne liest, ist der Schlüssel zur Optimierung der Abfrageleistung. In diesem Abschnitt gehen wir reale Beispiele für Aurora DSQL-Abfragepläne durch, zeigen, wie sich verschiedene Scantypen verhalten, erklären, wo Filter angewendet werden, und zeigen Optimierungsmöglichkeiten auf.
Beispiel für einen vollständigen Scan
Aurora DSQL verfügt sowohl über sequentielle Scans, die funktionell identisch mit PostgreSQL sind, als auch über vollständige Scans. Der einzige Unterschied zwischen diesen beiden besteht darin, dass bei vollständigen Scans zusätzliche Speicherfilterung verwendet werden kann. Aus diesem Grund wird diese Option fast immer über „Sequentielle Scans“ ausgewählt. Aufgrund der Ähnlichkeit werden wir nur Beispiele für die interessanteren vollständigen Scans behandeln.
Vollständige Scans werden hauptsächlich für Tabellen ohne Primärschlüssel verwendet. Da Aurora DSQL-Primärschlüssel standardmäßig Indizes vollständig abdecken, wird Aurora DSQL in vielen Situationen, in denen PostgreSQL einen sequentiellen Scan verwenden würde, höchstwahrscheinlich Index-Only-Scans für den Primärschlüssel verwenden. Wie bei den meisten anderen Datenbanken wird eine Tabelle ohne Indizes schlecht skaliert.
EXPLAIN SELECT account_id FROM transaction WHERE transaction_date > '2025-01-01' AND description LIKE '%external%';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Full Scan (btree-table) on transaction (cost=125100.05..177933.38 rows=33333 width=16)
Filter: (description ~~ '%external%'::text)
-> Storage Scan on transaction (cost=12510.05..17793.38 rows=66666 width=16)
Projections: account_id, description
Filters: (transaction_date > '2025-01-01 00:00:00'::timestamp without time zone)
-> B-Tree Scan on transaction (cost=12510.05..17793.38 rows=100000 width=30)
Dieser Plan zeigt zwei Filter, die in unterschiedlichen Phasen angewendet werden. Die transaction_date >
'2025-01-01' Bedingung wird auf die Speicherebene angewendet, wodurch die Menge der zurückgegebenen Daten reduziert wird. Die description LIKE '%external%' Bedingung wird später im Abfrageprozessor angewendet, nachdem Daten übertragen wurden, wodurch sie weniger effizient ist. Das Verschieben selektiverer Filter in die Speicher- oder Indexebene verbessert im Allgemeinen die Leistung.
Beispiel „Nur Index scannen“
Nur Index-Scans sind die optimalsten Scantypen in Aurora DSQL, da sie zu den wenigsten Roundtrips zur Speicherebene führen und am meisten filtern können. Aber nur weil Sie Index Only Scan sehen, heißt das nicht, dass Sie den besten Plan haben. Aufgrund der unterschiedlichen Filterstufen, die auftreten können, ist es wichtig, trotzdem darauf zu achten, an welchen Stellen gefiltert werden kann.
EXPLAIN SELECT balance FROM account WHERE customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb' AND balance > 100 AND status = 'pending';
QUERY PLAN
-------------------------------------------------------------------------------
Index Only Scan using idx1 on account (cost=725.05..1025.08 rows=8 width=18)
Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
Filter: (balance > '100'::numeric)
-> Storage Scan on idx1 (cost=12510.05..17793.38 rows=9 width=16)
Projections: balance
Filters: ((status)::text = 'pending'::text)
-> B-Tree Scan on idx1 (cost=12510.05..17793.38 rows=10 width=30)
Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
In diesem Plan wird die Indexbedingung customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb' () zuerst während des Indexscans ausgewertet. Dies ist die effizienteste Phase, da sie begrenzt, wie viele Daten aus dem Speicher gelesen werden. Der Speicherfilter,status = 'pending', wird nach dem Lesen der Daten, aber bevor sie an die Rechenebene gesendet werden, angewendet, wodurch die übertragene Datenmenge reduziert wird. Schließlich wird der Filter für den Abfrageprozessorbalance > 100,, zuletzt ausgeführt, nachdem die Daten verschoben wurden, was ihn am wenigsten effizient macht. Von diesen bietet die Indexbedingung die beste Leistung, da sie direkt steuert, wie viele Daten gescannt werden.
Beispiel für einen Index-Scan
Index-Scans ähneln Nur-Index-Scans, mit dem Unterschied, dass sie zusätzlich die Basistabelle aufrufen müssen. Da Aurora DSQL Speicherfilter angeben kann, ist dies sowohl beim Indexaufruf als auch beim Suchaufruf möglich.
Um dies zu verdeutlichen, präsentiert Aurora DSQL den Plan als zwei Knoten. Auf diese Weise können Sie deutlich erkennen, wie hilfreich das Hinzufügen einer Include-Spalte in Bezug auf die aus dem Speicher zurückgegebenen Zeilen ist.
EXPLAIN SELECT balance FROM account WHERE customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb' AND balance > 100 AND status = 'pending' AND created_at > '2025-01-01';
QUERY PLAN
----------------------------------------------------------------------------------------------------------
Index Scan using idx1 on account (cost=728.18..1132.20 rows=3 width=18)
Filter: (balance > '100'::numeric)
Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
-> Storage Scan on idx1 (cost=12510.05..17793.38 rows=8 width=16)
Projections: balance
Filters: ((status)::text = 'pending'::text)
-> B-Tree Scan on account (cost=12510.05..17793.38 rows=10 width=30)
Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
-> Storage Lookup on account (cost=12510.05..17793.38 rows=4 width=16)
Filters: (created_at > '2025-01-01 00:00:00'::timestamp without time zone)
-> B-Tree Lookup on transaction (cost=12510.05..17793.38 rows=8 width=30)
Dieser Plan zeigt, wie die Filterung über mehrere Stufen hinweg erfolgt:
-
Die Indexbedingung für
customer_idfiltert Daten frühzeitig. -
Durch den eingeschalteten Speicherfilter werden die Ergebnisse
statusweiter eingegrenzt, bevor sie an die Datenverarbeitung gesendet werden. -
Der aktivierte Filter für den Abfrageprozessor
balancewird später, nach der Übertragung, angewendet. -
Der aktivierte Suchfilter
created_atwird beim Abrufen zusätzlicher Spalten aus der Basistabelle ausgewertet.
Durch das Hinzufügen häufig verwendeter Spalten als INCLUDE Felder kann diese Suche häufig vermieden und die Leistung verbessert werden.
Bewährte Methoden
-
Richten Sie die Filter an den indizierten Spalten aus, um die Filterung früher voranzutreiben.
-
Verwenden Sie INCLUDE-Spalten, um reine Index-Scans zu ermöglichen und Suchvorgänge zu vermeiden.
-
Halten Sie die Statistiken auf dem neuesten Stand, um sicherzustellen, dass die Kosten- und Zeilenschätzungen korrekt sind.
-
Vermeiden Sie nicht indizierte Abfragen in großen Tabellen, um teure vollständige Scans zu vermeiden.