Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Query a shard singolo nel database Aurora PostgreSQL Limitless
Una query a shard singolo è una query che può essere eseguita direttamente su uno shard mantenendo la semantica di SQL ACID.
Questa ottimizzazione riduce il numero di round trip di rete dal router allo shard, migliorando le prestazioni. Attualmente questa ottimizzazione viene eseguita perINSERT
, SELECT
UPDATE
, e le DELETE
interrogazioni.
Argomenti
Esempi di query a frammento singolo
Negli esempi seguenti, abbiamo la tabella condivisacustomers
, con la chiave shardcustomer_id
, e la tabella di riferimento. 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)
- UPDATE
-
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)
Restrizioni per le query a shard singolo
Le query a shard singolo presentano le seguenti restrizioni:
- Funzioni
-
Se una query a shard singolo contiene una funzione, la query è idonea per l'ottimizzazione a shard singolo solo se si applica una delle seguenti condizioni:
-
La funzione è immutabile. Per ulteriori informazioni, consulta Volatilità della funzione.
-
La funzione è mutabile, ma è registrata nella vista.
rds_aurora.limitless_distributed_functions
Per ulteriori informazioni, consulta Distribuzione delle funzioni.
-
- Visualizzazioni
-
Se una query contiene una o più viste, l'ottimizzazione a shard singolo è disabilitata per la query se presenta una delle seguenti condizioni:
-
Qualsiasi vista ha l'
security_barrier
attributo. -
Gli oggetti utilizzati nella query richiedono più privilegi utente. Ad esempio, una query contiene due visualizzazioni che vengono eseguite da due utenti diversi.
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)
-
- Istruzioni PREPARE ed EXECUTE
-
Aurora PostgreSQL Limitless Database supporta l'ottimizzazione a shard singolo per le istruzioni preparate.
SELECT
Tuttavia, se l'istruzione preparata è un
UPDATE
oDELETE
e contiene una variabile preparata, il pianificatore di query rifiuta l'ottimizzazione a shard singolo per quella query. Ciò è illustrato negli esempi seguenti: l'Single Shard Optimized
indicatore è mancante.postgres_limitless=> PREPARE testStmt AS SELECT customer_name FROM customers c WHERE c.customer_id = $1; PREPARE postgres_limitless=> EXECUTE testStmt(1); customer_name --------------- (0 rows)
postgres_limitless=> EXPLAIN verbose EXECUTE testStmt(1); 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: 1520926022284463170 Remote SQL: SELECT customer_name FROM public.customers c WHERE (customer_id = $1) Query Identifier: 1520926022284463170 (11 rows)
- PL/pgSQL
-
Per le interrogazioni con PL/pgSQL variables are run as implicitly prepared statements. If a query contains any PL/pgSQL variabili, il pianificatore di query rifiuta l'ottimizzazione a shard singolo.
L'ottimizzazione è supportata nelle variabili. PL/pgSQL block if the statement doesn't contain any PL/pgSQL
Unioni completamente qualificate (esplicite)
L'ottimizzazione a shard singolo si basa sull'eliminazione delle partizioni. L'ottimizzatore PostgreSQL elimina le partizioni in base a condizioni costanti. Se Aurora PostgreSQL Limitless Database rileva che tutte le partizioni e le tabelle rimanenti si trovano sullo stesso shard, contrassegna la query come idonea per l'ottimizzazione a shard singolo. Tutte le condizioni di filtro devono essere esplicite affinché l'eliminazione delle partizioni funzioni. Aurora PostgreSQL Limitless Database non è in grado di eliminare le partizioni senza uno o più predicati di join o filtrare i predicati sulle chiavi shard di ogni tabella condivisa nell'istruzione.
Supponiamo di aver partizionato le tabelle, e in base alla colonna. customers
orders
order_details
customer_id
In questo schema, l'applicazione cerca di conservare tutti i dati di un cliente su un singolo shard.
Considera la query seguente:
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;
Questa query recupera tutti i dati di un cliente ()c.customer_id = 1
. I dati di questo cliente si trovano su un singolo shard, ma Aurora PostgreSQL Limitless Database non qualifica questa query come query a shard singolo. Il processo di ottimizzazione per la query è il seguente:
-
L'ottimizzatore può eliminare le partizioni per
customers
e inorders
base alla seguente condizione:c.customer_id = 1 c.customer_id = o.customer_id o.customer_id = 1 (transitive implicit condition)
-
L'ottimizzatore non può eliminare alcuna partizione perché non esiste una condizione costante sulla tabella.
order_details
-
L'ottimizzatore conclude di aver letto tutte le partizioni da.
order_details
Pertanto, la query non può essere qualificata per l'ottimizzazione a shard singolo.
Per renderla una query a shard singolo, aggiungiamo la seguente condizione di unione esplicita:
o.customer_id = od.customer_id
La query modificata ha il seguente aspetto:
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;
Ora l'ottimizzatore può eliminare le partizioni per. order_details
La nuova query diventa una query a frammento singolo e si qualifica per l'ottimizzazione.
Impostazione di una chiave shard attiva
Questa funzionalità consente di impostare una singola chiave shard durante l'interrogazione del database, facendo sì che tutte SELECT
le query DML vengano aggiunte con la chiave shard come predicato costante. Questa funzionalità è utile se hai effettuato la migrazione ad Aurora PostgreSQL Limitless Database e hai denormalizzato lo schema aggiungendo chiavi shard alle tabelle.
È possibile aggiungere automaticamente un predicato di chiave shard alla logica SQL esistente, senza modificare la semantica delle query. L'aggiunta di un predicato di chiave shard attiva viene eseguita solo per le tabelle compatibili.
La funzionalità active shard key utilizza la rds_aurora.limitless_active_shard_key
variabile, che ha la seguente sintassi:
SET [session | local] rds_aurora.limitless_active_shard_key = '{"col1_value", "col2_value", ...}';
Alcune considerazioni sulle chiavi shard attive e sulle chiavi esterne:
-
Una tabella condivisa può avere un vincolo di chiave esterna se le tabelle principale e secondaria sono collocate e la chiave esterna è un superset della chiave shard.
-
Una tabella condivisa può avere un vincolo di chiave esterna rispetto a una tabella di riferimento.
-
Una tabella di riferimento può avere un vincolo di chiave esterna rispetto a un'altra tabella di riferimento.
Supponiamo di avere una customers
tabella condivisa sulla colonna. 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;
Con un set di chiavi shard attivo, le query hanno le seguenti trasformazioni.
- 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');
- UPDATE
-
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;
- Join
-
Quando si eseguono operazioni di join su tabelle con una chiave shard attiva, il predicato della chiave shard viene aggiunto automaticamente a tutte le tabelle coinvolte nel join. Questa aggiunta automatica del predicato della chiave shard si verifica solo quando tutte le tabelle della query appartengono allo stesso gruppo di collocazione. Se la query riguarda tabelle di gruppi di collocazione diversi, viene invece generato un errore.
Supponiamo di avere
orders
anche delleorder_details
tabelle che sono collocate con lacustomers
tabella.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;
Recupera le ultime 10 fatture d'ordine per un cliente il cui ID cliente è 10.
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;
Questa interrogazione viene trasformata nella seguente:
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;
- Tabelle compatibili con Active Shard Key
-
Il predicato della chiave shard viene aggiunto solo alle tabelle compatibili con la chiave shard attiva. Una tabella è considerata compatibile se ha lo stesso numero di colonne nella chiave shard specificato nella variabile.
rds_aurora.limitless_active_shard_key
Se la query riguarda tabelle incompatibili con la chiave shard attiva, il sistema genera un errore invece di procedere con la query.Per esempio:
-- 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;