Leggere i piani di Aurora DSQL EXPLAIN - Amazon Aurora DSQL

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à.

Leggere i piani di Aurora DSQL EXPLAIN

Capire come leggere i piani EXPLAIN è fondamentale per ottimizzare le prestazioni delle query. In questa sezione, esamineremo esempi reali di piani di query DSQL di Aurora, mostreremo come si comportano i diversi tipi di scansione, spiegheremo dove vengono applicati i filtri ed evidenzieremo le opportunità di ottimizzazione.

Esempio di scansione completa

Aurora DSQL dispone sia di scansioni sequenziali, identiche dal punto di vista funzionale a PostgreSQL, sia di scansioni complete. L'unica differenza tra queste due è che le scansioni complete possono utilizzare filtri aggiuntivi sullo storage. Per questo motivo, viene quasi sempre selezionato al di sopra delle scansioni sequenziali. A causa della somiglianza, tratteremo solo esempi delle scansioni complete più interessanti.

Le scansioni complete verranno utilizzate principalmente su tabelle prive di chiave primaria. Poiché le chiavi primarie Aurora DSQL sono per impostazione predefinita indici a copertura completa, Aurora DSQL utilizzerà molto probabilmente Index Only Scans sulla chiave primaria in molte situazioni in cui PostgreSQL utilizzerebbe una scansione sequenziale. Come con la maggior parte degli altri database, una tabella senza indici si ridimensionerà male.

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)

Questo piano mostra due filtri applicati in fasi diverse. La transaction_date > '2025-01-01' condizione viene applicata a livello di archiviazione, riducendo la quantità di dati restituiti. La description LIKE '%external%' condizione viene applicata successivamente nel processore di query, dopo il trasferimento dei dati, rendendolo meno efficiente. L'inserimento di filtri più selettivi nei livelli di archiviazione o di indice generalmente migliora le prestazioni.

Esempio di scansione Index Only

Le scansioni indicizzate sono i tipi di scansione più ottimali in Aurora DSQL in quanto comportano il minor numero di round trip verso il livello di archiviazione e possono eseguire la maggior parte dei filtri. Ma solo perché vedi Index Only Scan non significa che tu abbia il piano migliore. A causa di tutti i diversi livelli di filtraggio che possono verificarsi, è essenziale prestare comunque attenzione ai diversi luoghi in cui può avvenire il filtraggio.

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 questo piano, la condizione dell'indice,customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'), viene valutata innanzitutto durante la scansione dell'indice, che è la fase più efficiente perché limita la quantità di dati letti dallo storage. Il filtro di archiviazione,status = 'pending', viene applicato dopo la lettura dei dati ma prima di essere inviati al livello di elaborazione, riducendo la quantità di dati trasferiti. Infine, il filtro del processore di query viene eseguito per ultimo, dopo lo spostamento dei dati, il che lo rende il meno efficiente. balance > 100 Di queste, la condizione dell'indice offre le prestazioni migliori perché controlla direttamente la quantità di dati scansionati.

Esempio di Index Scan

Le scansioni degli indici sono simili alle scansioni di solo indice, tranne per il fatto che hanno il passaggio aggiuntivo di dover richiamare la tabella di base. Poiché Aurora DSQL è in grado di specificare filtri di archiviazione, è in grado di farlo sia sulla chiamata di indice che sulla chiamata di ricerca.

Per chiarire questo punto, Aurora DSQL presenta il piano come due nodi. In questo modo, puoi vedere chiaramente quanto l'aggiunta di una colonna di inclusione possa aiutare in termini di righe restituite dall'archiviazione.

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)

Questo piano mostra come avviene il filtraggio in più fasi:

  • La condizione di indicizzazione customer_id filtra i dati in anticipo.

  • Il filtro di archiviazione limita status ulteriormente i risultati prima che vengano inviati al calcolo.

  • Il filtro del processore di query attivo balance viene applicato successivamente, dopo il trasferimento.

  • Il filtro di ricerca attivato created_at viene valutato quando si recuperano colonne aggiuntive dalla tabella di base.

L'aggiunta di colonne utilizzate di frequente come INCLUDE campi può spesso eliminare questa ricerca e migliorare le prestazioni.

Best practice

  • Allinea i filtri alle colonne indicizzate per accelerare il filtraggio.

  • Utilizza le colonne INCLUDE per consentire le scansioni solo indicizzate ed evitare le ricerche.

  • Mantieni aggiornate le statistiche per garantire che le stime dei costi e delle righe siano accurate.

  • Evita le query non indicizzate su tabelle di grandi dimensioni per evitare costose scansioni complete.