View a markdown version of this page

Optimieren von korrelierten Unterabfragen in Aurora PostgreSQL - Amazon Aurora

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.

Optimieren von korrelierten Unterabfragen in Aurora PostgreSQL

Eine korrelierte Unterabfrage verweist auf Tabellenspalten aus der äußeren Abfrage. Sie wird einmal für jede Zeile ausgewertet, die von der äußeren Abfrage zurückgegeben wird. Im folgenden Beispiel verweist die Unterabfrage auf eine Spalte aus der Tabelle „ot“. Diese Tabelle ist nicht in der FROM-Klausel der Unterabfrage enthalten, wird aber in der FROM-Klausel der äußeren Abfrage referenziert. Wenn die Tabelle „ot“ 1 Million Zeilen enthält, muss die Unterabfrage 1 Million Mal ausgewertet werden.

SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);
Anmerkung
  • Die Transformation einer Unterabfrage und der Unterabfragen-Cache sind in Aurora PostgreSQL ab Version 16.8 verfügbar, während Babelfish für Aurora PostgreSQL diese Funktionen ab Version 4.2.0 unterstützt.

  • Ab den Versionen 4.6.0 und 5.2.0 von Babelfish für Aurora PostgreSQL steuern die folgenden Parameter diese Funktionen:

    • babelfishpg_tsql.apg_enable_correlated_scalar_transform

    • babelfishpg_tsql.apg_enable_subquery_cache

    Beide Parameter sind standardmäßig deaktiviert.

Verbessern der Aurora-PostgreSQL-Abfrageleistung mithilfe der Unterabfragentransformation

Aurora PostgreSQL kann korrelierte Unterabfragen beschleunigen, indem sie in äquivalente äußere Joins umgewandelt werden. Diese Optimierung gilt für die folgenden zwei Typen korrelierter Unterabfragen:

  • Unterabfragen, die einen einzelnen Aggregatwert zurückgeben und in der SELECT-Liste aufgeführt sind

    SELECT ot.a, ot.b, (SELECT AVG(it.b) FROM it WHERE it.a = ot.a) FROM ot;
  • Unterabfragen, die einen einzelnen Aggregatwert zurückgeben und in einer WHERE-Klausel aufgeführt sind

    SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);

Aktivieren der Transformation in der Unterabfrage

Um die Transformation korrelierter Unterabfragen in äquivalente externe Joins zu ermöglichen, setzen Sie den apg_enable_correlated_scalar_transform-Parameter auf ON. Der Standardwert für diesen Parameter ist OFF.

Sie können die Cluster- oder Instance-Parametergruppe ändern, um diese Parameter festzulegen. Weitere Informationen hierzu finden Sie unter Parametergruppen für Amazon Aurora.

Alternativ können Sie die Einstellung mit dem folgenden Befehl ausschließlich für die aktuelle Sitzung konfigurieren:

SET apg_enable_correlated_scalar_transform TO ON;

Überprüfen der Transformation

Verwenden Sie den Befehl EXPLAIN, um zu überprüfen, ob die korrelierte Unterabfrage im Abfrageplan in einen externen Join umgewandelt wurde.

Wenn die Transformation aktiviert ist, wird der entsprechende korrelierte Teil der Unterabfrage in einen externen Join umgewandelt. Beispiel:

postgres=> CREATE TABLE ot (a INT, b INT); CREATE TABLE postgres=> CREATE TABLE it (a INT, b INT); CREATE TABLE postgres=> SET apg_enable_correlated_scalar_transform TO ON; SET postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a); QUERY PLAN -------------------------------------------------------------- Hash Join Hash Cond: (ot.a = apg_scalar_subquery.scalar_output) Join Filter: ((ot.b)::numeric < apg_scalar_subquery.avg) -> Seq Scan on ot -> Hash -> Subquery Scan on apg_scalar_subquery -> HashAggregate Group Key: it.a -> Seq Scan on it

Dieselbe Abfrage wird nicht umgewandelt, wenn der GUC-Parameter auf OFF gesetzt wird. Der Plan hat keinen externen Join, sondern stattdessen einen untergeordneten Plan (Subplan).

postgres=> SET apg_enable_correlated_scalar_transform TO OFF; SET postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a); QUERY PLAN ---------------------------------------- Seq Scan on ot Filter: ((b)::numeric < (SubPlan 1)) SubPlan 1 -> Aggregate -> Seq Scan on it Filter: (a = ot.a)

Einschränkungen

  • Die Unterabfrage muss in der SELECT-Liste oder in einer der Bedingungen der WHERE-Klausel enthalten sein. Andernfalls wird sie nicht umgewandelt.

  • Die Unterabfrage muss eine Aggregatfunktion zurückgeben. User-defined Aggregatfunktionen werden für die Transformation nicht unterstützt.

  • Eine Unterabfrage, deren Return-Ausdruck keine einfache Aggregatfunktion ist, wird nicht umgewandelt.

  • Die korrelierte Bedingung in den WHERE-Klauseln der Unterabfrage sollte ein einfacher Spaltenverweis sein. Andernfalls wird sie nicht umgewandelt.

  • Die korrelierte Bedingung in den Where-Klauseln der Unterabfrage muss ein einfaches Gleichheitsprädikat sein.

  • Die Unterabfrage darf weder eine HAVING- noch eine GROUP BY-Klausel enthalten.

  • Die WHERE-Klausel in der Unterabfrage kann ein oder mehrere Prädikate in Kombination mit AND enthalten.

Anmerkung

Die Auswirkungen der Transformation auf die Leistung hängen von Ihrem Schema, Ihren Daten und Ihrem Workload ab. Die Ausführung korrelierter Unterabfragen mit Transformation kann die Leistung erheblich verbessern, da die Anzahl der Zeilen, die von der äußeren Abfrage erzeugt werden, zunimmt. Es wird dringend empfohlen, diese Funktion in einer Nicht-Produktionsumgebung mit Ihrem tatsächlichen Schema, Ihren Daten und Ihrem Workload zu testen, ehe Sie sie in einer Produktionsumgebung aktivieren.

Verwenden des Unterabfrage-Caches zur Verbesserung der Aurora-PostgreSQL-Abfrageleistung

Aurora PostgreSQL unterstützt einen Unterabfrage-Cache zum Speichern der Ergebnisse korrelierter Unterabfragen. Diese Funktion überspringt wiederholte Ausführungen korrelierter Unterabfragen, wenn sich die Ergebnisse der Unterabfragen bereits im Cache befinden.

Grundlegendes zu Unterabfragen

Der Memoize-Knoten von PostgreSQL ist der wichtigste Teil des Unterabfrage-Caches. Der Memoize-Knoten verwaltet eine Hash-Tabelle im lokalen Cache, um Eingabeparameterwerte den Abfrageergebniszeilen zuzuordnen. Das Speicherlimit für die Hash-Tabelle ergibt sich aus work_mem und hash_mem_multiplier. Weitere Informationen finden Sie unter Ressourcennutzung.

Während der Ausführung der Abfrage verwendet der Unterabfragen-Cache die Cache-Trefferrate (CHR), um abzuschätzen, ob der Cache die Abfrageleistung verbessert, und um zur Laufzeit der Abfrage zu entscheiden, ob der Cache weiterhin verwendet werden soll. Die CHR gibt das Verhältnis der Anzahl von Cache-Treffern zur Gesamtzahl der Anfragen an. Wenn beispielsweise eine korrelierte Unterabfrage 100 Mal ausgeführt werden muss und 70 dieser Ausführungsergebnisse aus dem Cache abgerufen werden können, beträgt die CHR 0,7.

Für jede apg_subquery_cache_check_interval-Anzahl von Cache-Fehlern wird der Nutzen des Unterabfrage-Caches ausgewertet, indem geprüft wird, ob die CHR größer ist als apg_subquery_cache_hit_rate_threshold. Wenn nicht, wird der Cache aus dem Speicher gelöscht und die Abfrageausführung kehrt zur ursprünglichen, nicht zwischengespeicherten erneuten Ausführung der Unterabfrage zurück.

Parameter, die das Verhalten des Unterabfrage-Caches steuern

In der folgenden Tabelle sind die Parameter aufgeführt, die das Verhalten des Unterabfrage-Caches steuern.

Parameter

Description

Standard

Zulässig

apg_enable_subquery_cache

Aktiviert die Verwendung von Cache für korrelierte skalare Unterabfragen

OFF

ON, OFF

apg_subquery_cache_check_interval

Legt die Häufigkeit in Anzahl der Cache-Fehler fest, um die Unterabfragen-CHR zu bewerten.

500

0 – 2147483647

apg_subquery_cache_hit_rate_threshold

Legt den Schwellenwert für die Unterabfragen-CHR fest.

0.3

0,0 bis 1,0
Anmerkung
  • Größere Werte von apg_subquery_cache_check_interval können die Genauigkeit der Schätzung des CHR-based Cache-Nutzens verbessern, erhöhen jedoch den Cache-Overhead, da CHR erst ausgewertet wird, wenn die Cachetabelle Zeilen enthältapg_subquery_cache_check_interval.

  • Höhere Werte von apg_subquery_cache_hit_rate_threshold bedeuten, dass der Unterabfrage-Cache aufgegeben wurde und zur ursprünglichen, erneuten Ausführung der Unterabfrage ohne Zwischenspeicherung zurückgekehrt wird.

Sie können die Cluster- oder Instance-Parametergruppe ändern, um diese Parameter festzulegen. Weitere Informationen hierzu finden Sie unter Parametergruppen für Amazon Aurora.

Alternativ können Sie die Einstellung mit dem folgenden Befehl ausschließlich für die aktuelle Sitzung konfigurieren:

SET apg_enable_subquery_cache TO ON;

Aktivieren des Unterabfrage-Caches in Aurora PostgreSQL

Wenn der Unterabfrage-Cache aktiviert ist, nutzt Aurora PostgreSQL Cache, um die Ergebnisse der Unterabfrage zu speichern. Unter dem Abfrageplan befindet sich dann ein Memoize-Knoten. SubPlan

Die folgende Befehlssequenz zeigt beispielsweise den geschätzten Abfrageausführungsplan einer einfachen korrelierten Unterabfrage ohne Unterabfrage-Cache.

postgres=> SET apg_enable_subquery_cache TO OFF; SET postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT it.b FROM it WHERE it.a = ot.a); QUERY PLAN ------------------------------------ Seq Scan on ot Filter: (b < (SubPlan 1)) SubPlan 1 -> Seq Scan on it Filter: (a = ot.a)

Nach dem apg_enable_subquery_cache Einschalten enthält der Abfrageplan einen Memoize-Knoten unter dem Knoten, der SubPlan darauf hinweist, dass die Unterabfrage beabsichtigt, den Cache zu verwenden.

postgres=> SET apg_enable_subquery_cache TO ON; SET postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT it.b FROM it WHERE it.a = ot.a); QUERY PLAN ------------------------------------ Seq Scan on ot Filter: (b < (SubPlan 1)) SubPlan 1 -> Memoize Cache Key: ot.a Cache Mode: binary -> Seq Scan on it Filter: (a = ot.a)

Der eigentliche Ausführungsplan für die Abfrage enthält weitere Details zum Unterabfrage-Cache, einschließlich Cache-Treffer und Cache-Fehler. Die folgende Ausgabe zeigt den tatsächlichen Abfrageausführungsplan der obigen Beispielabfrage nach dem Einfügen einiger Werte in die Tabellen.

postgres=> EXPLAIN (COSTS FALSE, TIMING FALSE, ANALYZE TRUE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT it.b FROM it WHERE it.a = ot.a); QUERY PLAN ----------------------------------------------------------------------------- Seq Scan on ot (actual rows=2 loops=1) Filter: (b < (SubPlan 1)) Rows Removed by Filter: 8 SubPlan 1 -> Memoize (actual rows=0 loops=10) Cache Key: ot.a Cache Mode: binary Hits: 4 Misses: 6 Evictions: 0 Overflows: 0 Memory Usage: 1kB -> Seq Scan on it (actual rows=0 loops=6) Filter: (a = ot.a) Rows Removed by Filter: 4

Die Gesamtzahl der Cache-Treffer ist 4 und die Gesamtzahl der Cache-Fehler beträgt 6. Wenn die Gesamtzahl der Treffer und Fehler geringer ist als die Anzahl der Schleifen im Memoize-Knoten, bedeutet das, dass die CHR-Evaluierung nicht erfolgreich war und der Cache an irgendeinem Punkt bereinigt und aufgegeben wurde. Hinsichtlich der Ausführung der Unterabfrage wurde dann die ursprüngliche, erneute Ausführung ohne Zwischenspeicherung wiederaufgenommen.

Einschränkungen

Der Unterabfrage-Cache unterstützt bestimmte Muster korrelierter Unterabfragen nicht. Diese Arten von Abfragen werden ohne Cache ausgeführt, auch wenn der Unterabfrage-Cache aktiviert ist:

  • IN/EXISTS/ANY/ALL korrelierte Unterabfragen

  • Korrelierte Unterabfragen, die nicht deterministische Funktionen enthalten

  • Korrelierte Unterabfragen, die auf äußere Tabellenspalten mit Datentypen verweisen, die keine Hashing- oder Gleichheitsoperationen unterstützen.

Verbesserung der Aurora PostgreSQL-Abfrageleistung mithilfe der Transformation von Unterabfragefenstern

Aurora PostgreSQL kann korrelierte aggregierte Unterabfragen beschleunigen, indem sie in äquivalente Fensterfunktionen umgewandelt werden. Diese Optimierung gilt für skalare korrelierte Unterabfragen in einer WHERE-Klausel, die einen äußeren Ausdruck mit einem Aggregat vergleichen, wie z. B. das folgende Abfragemuster:

SELECT o.id, o.amount FROM orders o, products p WHERE p.id = o.product_id AND o.amount < ( SELECT 0.2 * avg(o2.amount) FROM orders o2 WHERE o2.product_id = p.id );

Bei der Transformation handelt es sich um eine Neuschreibung auf Planebene, bei der nur der Ausführungsplan, nicht die Abfrageergebnisse geändert werden.

Anmerkung

Die Transformation von Unterabfragefenstern ist in Aurora PostgreSQL ab Version 18.6 verfügbar, während Babelfish für Aurora PostgreSQL diese Funktion ab 6.2.0 unterstützt. Für Babelfish for Aurora PostgreSQL wird die Funktion durch den babelfishpg_tsql.apg_enable_subquery_to_window_transform Parameter gesteuert, der standardmäßig aktiviert ist. ON

Wann sollte die Fenstertransformation für Unterabfragen verwendet werden

Erwägen Sie, diese Transformation zu aktivieren, wenn Sie Abfragen haben, die dem Selbstkorrelationsmuster entsprechen: eine äußere Zeile wird mit einem Aggregat verglichen, das anhand derselben Tabelle mit einer Korrelationsbedingung berechnet wurde.

Diese Transformation ergänzt die bestehende Transformation für korrelierte Unterabfragen, bei der korrelierte Unterabfragen in äußere Verknüpfungen umgeschrieben werden. Die Fenstertransformation für Unterabfragen schreibt sie stattdessen als Fensterfunktionen um. Die beiden Transformationen decken unterschiedliche Muster ab:

  • Die korrelierte Unterabfragetransformation gilt für Unterabfragen sowohl in der SELECT-Liste als auch in der WHERE-Klausel. Die Unterabfrage muss eine Aggregatfunktion wie avg(x) oder count(*) ohne einen umgebenden Ausdruck zurückgeben.

  • Die Transformation für das Fenster der Unterabfrage gilt nur für WHERE-clause Unterabfragen, die das Selbstkorrelationsmuster verwenden, wobei die Tabelle der Unterabfrage auch im äußeren FROM erscheint. Sie unterstützt außerdem Fälle, in denen das Aggregat mit einem konstanten Faktor kombiniert wird (z. B.0.2 * avg(o2.amount)), den die korrelierte Unterabfragetransformation nicht verarbeiten kann.

Sie können beide Transformationen gleichzeitig aktivieren. Wenn eine Abfrage für beide geeignet ist, wird die Transformation für das Fenster der Unterabfrage angewendet. Wenn sie nur für eine qualifiziert ist, wird diese Transformation angewendet.

Fenstertransformation für Unterabfragen aktivieren

Um die Umwandlung korrelierter aggregierter Unterabfragen in Fensterfunktionen zu ermöglichen, setzen Sie den apg_enable_subquery_to_window_transform Parameter auf. ON Der Standardwert für diesen Parameter ist OFF.

Sie können die Cluster- oder Instance-Parametergruppe ändern, um diese Parameter festzulegen. Weitere Informationen hierzu finden Sie unter Parametergruppen für Amazon Aurora.

Alternativ können Sie die Einstellung mit dem folgenden Befehl ausschließlich für die aktuelle Sitzung konfigurieren:

SET apg_enable_subquery_to_window_transform TO ON;

Um die Transformation zu deaktivieren, stellen Sie den Parameter so ein, dass er dieselben OFF Methoden verwendet. Änderungen werden wirksam, ohne dass die Instanz neu gestartet wird. SET auf Sitzungsebene wird sofort wirksam, und Änderungen an Parametergruppen gelten für neue Verbindungen.

Anmerkung

babelfishpg_tsql.apg_enable_subquery_to_window_transformSteuert für Babelfish for Aurora PostgreSQL nur, ob die Transformation gilt. Der apg_enable_subquery_to_window_transform Parameter hat im Dialekt keine Wirkung. T-SQL

Überprüfen der Transformation

Verwenden Sie den Befehl EXPLAIN, um zu überprüfen, ob die korrelierte Unterabfrage im Abfrageplan in eine Fensterfunktion umgewandelt wurde.

Wenn die Transformation aktiviert ist, enthält der Abfrageplan einen WindowAgg Knoten anstelle eines SubPlan Knotens. Beispiel:

postgres=> SET apg_enable_subquery_to_window_transform TO ON; SET postgres=> EXPLAIN (COSTS FALSE) SELECT o.id, o.amount FROM orders o, products p WHERE p.id = o.product_id AND o.amount < ( SELECT 0.2 * avg(o2.amount) FROM orders o2 WHERE o2.product_id = p.id ); QUERY PLAN ------------------------------------------------------ Subquery Scan on _sw Filter: (_sw.amount < (0.2 * _sw._w_agg_result)) -> WindowAgg Window: w1 AS (PARTITION BY o.product_id) -> Sort Sort Key: o.product_id -> Hash Join Hash Cond: (o.product_id = p.id) -> Seq Scan on orders o -> Hash -> Seq Scan on products p

Dieselbe Abfrage wird nicht umgewandelt, wenn der GUC-Parameter auf OFF gesetzt wird. Der Plan wird keinen WindowAgg Knoten haben, sondern SubPlan stattdessen einen.

postgres=> SET apg_enable_subquery_to_window_transform TO OFF; SET postgres=> EXPLAIN (COSTS FALSE) SELECT o.id, o.amount FROM orders o, products p WHERE p.id = o.product_id AND o.amount < ( SELECT 0.2 * avg(o2.amount) FROM orders o2 WHERE o2.product_id = p.id ); QUERY PLAN --------------------------------------------- Hash Join Hash Cond: (o.product_id = p.id) Join Filter: (o.amount < (SubPlan 1)) -> Seq Scan on orders o -> Hash -> Seq Scan on products p SubPlan 1 -> Aggregate -> Seq Scan on orders o2 Filter: (product_id = p.id)
Anmerkung

Verwenden Sie für Babelfish for Aurora PostgreSQL die folgenden Befehle, um die Transformation zu überprüfen.

Um die Transformation innerhalb einer Sitzung ein- oder auszuschalten:

SELECT set_config('babelfishpg_tsql.apg_enable_subquery_to_window_transform', 'true', false); SELECT set_config('babelfishpg_tsql.apg_enable_subquery_to_window_transform', 'false', false);

So zeigen Sie den Abfrageplan an:

SET BABELFISH_SHOWPLAN_ALL ON -- run your query SET BABELFISH_SHOWPLAN_ALL OFF

Einschränkungen

Wenn eine Abfrage diese Bedingungen nicht erfüllt, wird sie mit ihrem ursprünglichen Plan ausgeführt. Es wird kein Fehler ausgelöst.

  • Die Transformation gilt nur für eine skalare Unterabfrage in der WHERE-Klausel der äußeren Abfrage. Unterabfragen in der SELECT-Liste und Unterabfragen, die in einer OR-Bedingung verschachtelt sind, werden nicht transformiert. UND zusammen mit anderen Prädikaten wird unterstützt.

  • Die FROM-Klausel der Unterabfrage muss auf genau eine Tabelle verweisen, und dieselbe Tabelle muss genau einmal in der FROM-Klausel der äußeren Abfrage vorkommen. Verweise über eine Ansicht oder CTE zählen nicht als dieselbe Tabelle.

  • Die äußere Abfrage darf durchweg nur innere Verknüpfungen verwenden. Äußere Verknüpfungen, LATERAL-Referenzen, CTEs, Fensterfunktionen und Gruppierungssätze (CUBE, ROLLUP, GROUPING SETS) an beliebiger Stelle in der äußeren Abfrage disqualifizieren sie.

  • Das Ziel der Unterabfrage muss ein unterstütztes integriertes Aggregat (SUM, COUNT, AVG, MIN oder MAX) sein, das optional mit Literalkonstanten kombiniert werden kann (z. B.). 0.2 * avg(o2.amount) Ordered-set und benutzerdefinierte Aggregate wie ARRAY_AGG, STRING_AGG, JSON_AGG und PERCENTILE_CONT werden nicht unterstützt.

  • Das korrelierte Prädikat muss eine einfache Gleichheit (=) zwischen einfachen Spaltenverweisen auf beiden Seiten sein. Zusammengesetzte Schlüssel (mehrere UND-Gleichheiten) sind zulässig, solange jede Spalte auf der äußeren Seite zu derselben äußeren Tabelle gehört. Zusätzliche nicht korrelierte Prädikate in der Unterabfragetabelle können mit AND kombiniert werden.

  • Die Unterabfrage darf keine GROUP BY-, HAVING-, LIMIT-, ORDER BY-, DISTINCT- oder FOR UPDATE-Klausel, Mengenoperationen (UNION, INTERSECT, EXCEPT), Funktionen zur Rückgabe von Mengen, Fensterfunktionen, CTEs, verschachtelte Unterabfragen oder flüchtige Funktionen wie oder enthalten. random() clock_timestamp()

  • Die Verknüpfung zwischen der korrelierten Tabelle und jeder anderen äußeren Tabelle muss sich in einer Spalte mit einem Primärschlüssel oder einer eindeutigen Einschränkung befinden, sodass höchstens eine Zeile aus der anderen äußeren Tabelle mit jeder Zeile aus der korrelierten Tabelle übereinstimmt.

Anmerkung

Die Auswirkungen der Transformation auf die Leistung hängen von Ihrem Schema, Ihren Daten und Ihrer Arbeitslast ab. Die korrelierte Ausführung von Unterabfragen mit der Transformation von Fensterfunktionen kann die Leistung erheblich verbessern, wenn die Anzahl der Zeilen, die von der äußeren Abfrage erzeugt werden, zunimmt. Es wird dringend empfohlen, diese Funktion in einer Nicht-Produktionsumgebung mit Ihrem tatsächlichen Schema, Ihren Daten und Ihrem Workload zu testen, ehe Sie sie in einer Produktionsumgebung aktivieren.