Single-Shard-Abfragen in Aurora PostgreSQL Limitless Database - 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.

Single-Shard-Abfragen in Aurora PostgreSQL Limitless Database

Eine Single-Shard-Abfrage ist eine Abfrage, die direkt auf einem Shard ausgeführt werden kann, wobei die SQL-ACID-Semantik beibehalten wird. Wenn der Abfrageplaner auf dem Router auf eine solche Abfrage trifft, erkennt der Planer sie und leitet die gesamte SQL-Abfrage an den entsprechenden Shard weiter.

Diese Optimierung reduziert die Anzahl der Netzwerk-Roundtrips vom Router zum Shard und verbessert die Leistung. Derzeit wird diese Optimierung für die Abfragen INSERT, SELECT, UPDATE und DELETE durchgeführt.

Beispiele für Single-Shard-Abfragen

Die folgenden Beispiele umfassen die Sharded-Tabelle customers mit dem Shard-Schlüssel customer_id und die Referenztabelle zipcodes.

SELECT
postgres_limitless=> EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM customers WHERE customer_id = 100; QUERY PLAN --------------------------------------------------------- Foreign Scan Output: customer_id, other_id, customer_name, balance Remote SQL: SELECT customer_id, other_id, customer_name, balance FROM public.customers WHERE (customer_id = 100) Single Shard Optimized (9 rows)
postgres_limitless=> EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM orders LEFT JOIN zipcodes ON orders.zipcode_id = zipcodes.zipcode_id WHERE customer_id = 11; QUERY PLAN --------------------------------------------------------------------------------------------------------- Foreign Scan Output: customer_id, order_id, zipcode_id, customer_name, balance, zipcodes.zipcode_id, zipcodes.city Remote SQL: SELECT orders.customer_id, orders.order_id, orders.zipcode_id, orders.customer_name, orders.balance, zipcodes.zipcode_id, zipcodes.city FROM (public.orders LEFT JOIN public.zipcodes ON ((orders.zipcode_id = zipcodes.zipcode_id))) WHERE (orders.customer_id = 11) Single Shard Optimized (13 rows)
INSERT
postgres_limitless=> EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO customers (customer_id, other_id, customer_name, balance) VALUES (1, 10, 'saikiran', 1000); QUERY PLAN ------------------------------------------------------- Insert on public.customers -> Result Output: 1, 10, 'saikiran'::text, '1000'::real Single Shard Optimized (4 rows)
AKTUALISIERUNG
postgres_limitless=> EXPLAIN (VERBOSE, COSTS OFF) UPDATE orders SET balance = balance + 100 WHERE customer_id = 100; QUERY PLAN --------------------------------------------------------------------------------------------- Update on public.orders Foreign Update on public.orders_fs00002 orders_1 -> Foreign Update Remote SQL: UPDATE public.orders SET balance = (balance + (100)::double precision) WHERE (customer_id = 100) Single Shard Optimized (6 rows)
DELETE
postgres_limitless=> EXPLAIN (VERBOSE, COSTS OFF) DELETE FROM orders WHERE customer_id = 100 and balance = 0; QUERY PLAN --------------------------------------------------------------------- Delete on public.orders Foreign Delete on public.orders_fs00002 orders_1 -> Foreign Delete Remote SQL: DELETE FROM public.orders WHERE ((customer_id = 100) AND (balance = (0)::double precision)) Single Shard Optimized (6 rows)

Einschränkungen für Single-Shard-Abfragen

Für Single-Shard-Abfragen gelten die folgenden Einschränkungen:

Funktionen

Wenn eine Single-Shard-Abfrage eine Funktion enthält, kommt die Abfrage nur dann für die Single-Shard-Optimierung in Frage, wenn eine der folgenden Bedingungen zutrifft:

  • Die Funktion ist unveränderlich. Weitere Informationen finden Sie unter Funktionsvolatilität.

  • Die Funktion ist veränderbar, aber in der Ansicht rds_aurora.limitless_distributed_functions registriert. Weitere Informationen finden Sie unter Verteilung der Funktionen.

Ansichten

Wenn eine Abfrage eine oder mehrere Ansichten enthält, ist die Single-Shard-Optimierung für die Abfrage deaktiviert, wenn sie eine der folgenden Bedingungen erfüllt:

  • Jede Ansicht hat das Attribut security_barrier.

  • Für die in der Abfrage verwendeten Objekte sind mehrere Benutzerberechtigungen erforderlich. Eine Abfrage enthält beispielsweise zwei Ansichten, und die Ansichten werden unter zwei verschiedenen Benutzern ausgeführt.

CREATE VIEW v1 AS SELECT customer_name FROM customers c WHERE c.customer_id = 1; CREATE VIEW v2 WITH (security_barrier) AS SELECT customer_name FROM customers c WHERE c.customer_id = 1; postgres_limitless=> EXPLAIN VERBOSE SELECT * FROM v1; QUERY PLAN ------------------------------------------------------------------------------------ Foreign Scan (cost=100.00..101.00 rows=100 width=0) Output: customer_name Remote Plans from Shard postgres_s3: Seq Scan on public.customers_ts00001 c (cost=0.00..24.12 rows=6 width=32) Output: c.customer_name Filter: (c.customer_id = 1) Query Identifier: -6005737533846718506 Remote SQL: SELECT customer_name FROM ( SELECT c.customer_name FROM public.customers c WHERE (c.customer_id = 1)) v1 Query Identifier: -5754424854414896228 (12 rows) postgres_limitless=> EXPLAIN VERBOSE SELECT * FROM v2; QUERY PLAN -------------------------------------------------------------------------------------------- Foreign Scan on public.customers_fs00001 c (cost=100.00..128.41 rows=7 width=32) Output: c.customer_name Remote Plans from Shard postgres_s3: Seq Scan on public.customers_ts00001 customers (cost=0.00..24.12 rows=6 width=32) Output: customers.customer_name Filter: (customers.customer_id = 1) Query Identifier: 4136563775490008117 Remote SQL: SELECT customer_name FROM public.customers WHERE ((customer_id = 1)) Query Identifier: 5056054318010163757 (9 rows)
Anweisungen PREPARE und EXECUTE

Aurora PostgreSQL Limitless Database unterstützt die Single-Shard-Optimierung für vorbereitete SELECT-, UPDATE- und DELETE-Anweisungen.

Wenn Sie jedoch vorbereitete Anweisungen für PREPARE und EXECUTE verwenden und plan_cache_mode dabei auf 'force_generic_plan' festgelegt haben, lehnt der Abfrageplaner die Single-Shard-Optimierung für diese Abfrage ab.

PL/pgSQL

Abfragen mit PL/pgSQL-Variablen werden als implizit vorbereitete Anweisungen ausgeführt. Wenn eine Abfrage PL/pgSQL-Variablen enthält, lehnt der Abfrageplaner die Single-Shard-Optimierung ab.

Die Optimierung wird im PL/pgSQL-Block unterstützt, wenn die Anweisung keine PL/pgSQL-Variablen enthält.

Vollständig qualifizierte (explizite) Joins

Die Single-Shard-Optimierung basiert auf der Eliminierung von Partitionen. Der PostgreSQL-Optimierer eliminiert Partitionen auf der Grundlage konstanter Bedingungen. Wenn Aurora PostgreSQL Limitless Database feststellt, dass sich alle verbleibenden Partitionen und Tabellen auf demselben Shard befinden, markiert sie die Abfrage, die für die Single-Shard-Optimierung in Frage kommt. Alle Filterbedingungen müssen explizit sein, damit das Eliminieren von Partitionen funktioniert. Aurora PostgreSQL Limitless Database kann Partitionen ohne ein oder mehrere Join- oder Filterprädikate in den Shard-Schlüsseln jeder Sharded-Tabelle in der Anweisung nicht eliminieren.

Gehen Sie davon aus, dass wir die Tabellen customers, orders und order_details auf Grundlage der Spalte customer_id partitioniert haben. In diesem Schema versucht die Anwendung, alle Daten für einen Kunden auf einem einzigen Shard zu speichern.

Betrachten Sie folgende Abfrage:

SELECT * FROM customers c, orders o, order_details od WHERE c.customer_id = o.customer_id AND od.order_id = o.order_id AND c.customer_id = 1;

Diese Abfrage ruft alle Daten für einen Kunden (c.customer_id = 1) ab. Die Daten für diesen Kunden befinden sich auf einem einzigen Shard, aber Aurora PostgreSQL Limitless Database qualifiziert diese Abfrage nicht als Single-Shard-Abfrage. Der Optimierungsprozess für die Abfrage sieht wie folgt aus:

  1. Der Optimierer kann Partitionen für customers und orders auf Grundlage der folgenden Bedingung entfernen:

    c.customer_id = 1 c.customer_id = o.customer_id o.customer_id = 1 (transitive implicit condition)
  2. Der Optimierer kann keine Partitionen für order_details eliminieren, da es in der Tabelle keine konstante Bedingung gibt.

  3. Der Optimierer kommt zu dem Schluss, dass er alle Partitionen aus order_details gelesen hat. Daher kann die Abfrage nicht für die Single-Shard-Optimierung qualifiziert werden.

Um sie zu einer Single-Shard-Abfrage zu machen, fügen wir die folgende explizite Join-Bedingung hinzu:

o.customer_id = od.customer_id

Die geänderte Abfrage sieht wie folgt aus:

SELECT * FROM customers c, orders o, order_details od WHERE c.customer_id = o.customer_id AND o.customer_id = od.customer_id AND od. order_id = o. order_id AND c.customer_id = 1;

Jetzt kann der Optimierer Partitionen für order_details eliminieren. Die neue Abfrage wird zu einer Single-Shard-Abfrage und ist für die Optimierung geeignet.

Festlegen eines aktiven Shard-Schlüssels

Mit diesem Feature können Sie bei der Abfrage der Datenbank einen einzelnen Shard-Schlüssel festlegen, wodurch an alle SELECT- und DML-Abfragen der Shard-Schlüssel als konstantes Prädikat angehängt wird. Diese Funktion ist nützlich, wenn Sie eine Migration zu Aurora PostgreSQL Limitless Database durchgeführt und das Schema durch Hinzufügen von Shard-Schlüsseln zu Tabellen denormalisiert haben.

Sie können ein Shard-Schlüsselprädikat automatisch an die bestehende SQL-Logik anhängen, ohne die Semantik der Abfragen zu ändern. Das Anhängen eines aktiven Shard-Schlüsselprädikats erfolgt nur für kompatible Tabellen.

Das Feature Aktiver Shard-Schlüssel verwendet die Variable rds_aurora.limitless_active_shard_key, die die folgende Syntax hat:

SET [session | local] rds_aurora.limitless_active_shard_key = '{"col1_value", "col2_value", ...}';

Einige Überlegungen zu aktiven Shard-Schlüsseln und Fremdschlüsseln:

  • Für eine Sharded-Tabelle kann eine Fremdschlüsselbeschränkung gelten, wenn die übergeordneten und untergeordneten Tabellen nebeneinander angeordnet sind und der Fremdschlüssel eine Obermenge des Shard-Schlüssels bildet.

  • Für eine Sharded-Tabelle kann eine Fremdschlüsselbeschränkung hinsichtlich einer Referenztabelle gelten.

  • Für eine Referenztabelle kann eine Fremdschlüsselbeschränkung hinsichtlich einer anderen Referenztabelle gelten.

Nehmen wir an, wir haben eine customers-Tabelle mit angewendetem Sharding in der Spalte customer_id.

BEGIN; SET local rds_aurora.limitless_create_table_mode='sharded'; SET local rds_aurora.limitless_create_table_shard_key='{"customer_id"}'; CREATE TABLE customers(customer_id int PRIMARY KEY, name text , email text); COMMIT;

Bei einem aktiven Shard-Schlüsselsatz weisen Abfragen die folgenden Transformationen auf.

SELECT
SET rds_aurora.limitless_active_shard_key = '{"123"}'; SELECT * FROM customers; -- This statement is changed to: SELECT * FROM customers WHERE customer_id = '123'::int;
INSERT
SET rds_aurora.limitless_active_shard_key = '{"123"}'; INSERT INTO customers(name, email) VALUES('Alex', 'alex@example.com'); -- This statement is changed to: INSERT INTO customers(customer_id, name, email) VALUES('123'::int, 'Alex', 'alex@example.com');
AKTUALISIERUNG
SET rds_aurora.limitless_active_shard_key = '{"123"}'; UPDATE customers SET email = 'alex_new_email@example.com'; -- This statement is changed to: UPDATE customers SET email = 'alex_new_email@example.com' WHERE customer_id = '123'::int;
DELETE
SET rds_aurora.limitless_active_shard_key = '{"123"}'; DELETE FROM customers; -- This statement is changed to: DELETE FROM customers WHERE customer_id = '123'::int;
Joins

Wenn an Tabellen mit einem aktiven Shard-Schlüssel Join-Operationen ausgeführt werden, wird das Shard-Schlüssel-Prädikat automatisch allen an der Verknüpfung beteiligten Tabellen hinzugefügt. Dieses automatische Hinzufügen des Shard-Schlüssel-Prädikats erfolgt nur, wenn alle Tabellen in der Abfrage derselben Kollokationsgruppe angehören. Wenn die Abfrage Tabellen aus verschiedenen Kollokationsgruppen umfasst, wird stattdessen ein Fehler ausgelöst.

Gehen Sie davon aus, dass wir auch über orders- und order_details-Tabellen verfügen, die mit der customers-Tabelle zusammengefasst sind.

SET local rds_aurora.limitless_create_table_mode='sharded'; SET local rds_aurora.limitless_create_table_collocate_with='customers'; SET local rds_aurora.limitless_create_table_shard_key='{"customer_id"}'; CREATE TABLE orders (id int , customer_id int, total_amount int, date date); CREATE TABLE order_details (id int , order_id int, customer_id int, product_name VARCHAR(100), price int); COMMIT;

Hier rufen wir die letzten 10 Bestellrechnungen für einen Kunden ab, dessen Kundennummer 10 ist.

SET rds_aurora.limitless_active_shard_key = '{"10"}'; SELECT * FROM customers, orders, order_details WHERE orders.customer_id = customers.customer_id AND order_details.order_id = orders.order_id AND customers.customer_id = 10 order by order_date limit 10;

Diese Abfrage wird in Folgende transformiert:

SELECT * FROM customers, orders, order_details WHERE orders.customer_id = customers.customer_id AND orders.order_id = order_details.order_id AND customers.customer_id = 10 AND order_details.customer_id = 10 AND orders.customer_id = 10 AND ORDER BY "order_date" LIMIT 10;
Tabellen, die mit aktiven Shard-Schlüsseln kompatibel sind

Das Shard-Schlüssel-Prädikat wird nur zu Tabellen hinzugefügt, die mit dem aktiven Shard-Schlüssel kompatibel sind. Eine Tabelle gilt als kompatibel, wenn ihr Shard-Schlüssel genau die Anzahl von Spalten enthält, die in der Variablen rds_aurora.limitless_active_shard_key angegeben ist. Wenn die Abfrage Tabellen umfasst, die nicht mit dem aktiven Shard-Schlüssel kompatibel sind, gibt das System einen Fehler aus, anstatt mit der Abfrage fortzufahren.

Zum Beispiel:

-- Compatible table SET rds_aurora.limitless_active_shard_key = '{"10"}'; -- The following query works because the customers table is sharded on one column. SELECT * FROM customers; -- Incompatible table SET rds_aurora.limitless_active_shard_key = '{"10","20"}'; -- The following query raises a error because the customers table isn't sharded on two columns. SELECT * FROM customers;