

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

# Piano di esecuzione
<a name="aurora-analytics-execution-plan"></a>

Aurora PostgreSQL si integra con l'infrastruttura EXPLAIN di PostgreSQL per aiutarti a capire come vengono eseguite le query, identificare le opportunità di pushdown e diagnosticare i problemi di prestazioni. Questo argomento spiega come leggere i piani di esecuzione delle query su tabelle esterne, i diversi tipi di piano e i fattori che influenzano le scelte dei piani.

**Topics**
+ [Tipi di piano](#aurora-analytics-plan-types)
+ [Lettura di un piano di esecuzione: procedura dettagliata](#aurora-analytics-reading-plan-walkthrough)
+ [Utilizzo di EXPLAIN VERBOSE per visualizzare Pushdown SQL](#aurora-analytics-explain-verbose)
+ [Comprensione delle «espressioni pushdown non supportate»](#aurora-analytics-unsupported-pushdown)
+ [Ottimizzazione delle query per un pushdown completo](#aurora-analytics-tuning-pushdown)
+ [EXPLAIN, il riferimento alle metriche di](#aurora-analytics-explain-analyze-metrics)
+ [Suggerimenti per l'analisi del piano di esecuzione](#aurora-analytics-tips)

## Tipi di piano
<a name="aurora-analytics-plan-types"></a>

Aurora PostgreSQL utilizza due strategie pushdown, scelte automaticamente dal pianificatore:

**Topics**
+ [Pushdown completo delle interrogazioni](#aurora-analytics-full-pushdown)
+ [Table-scan pushdown (fallback)](#aurora-analytics-table-scan-pushdown)

### Pushdown completo delle interrogazioni
<a name="aurora-analytics-full-pushdown"></a>

L'intera query (inclusi JOIN, aggregazioni, sottoquery, CTE, ORDER BY e LIMIT) viene inviata al motore di analisi. Questo è il percorso di esecuzione più veloce.

Viene visualizzato un singolo `Custom Scan` nodo al livello superiore del piano:

```
EXPLAIN (COSTS OFF) SELECT status, count(*), sum(total_amount)
FROM ft_orders
WHERE order_date > '2024-01-01'
GROUP BY status
ORDER BY sum(total_amount) DESC
LIMIT 5;
```

```
                 QUERY PLAN
--------------------------------------------
 Custom Scan
   ->  TOP_N
         Top: 5
         Order By: sum(total_amount) DESC
         ->  HASH_GROUP_BY
               Groups: #0
               Aggregates: count_star(), sum(#1)
               ->  READ_PARQUET
                     Table: ft_orders
                     Filters: order_date>'2024-01-01'
                     Projections: status, total_amount
```

Tutto all'interno di `Custom Scan` viene eseguito dal motore di analisi utilizzando l'elaborazione colonnare.

### Table-scan pushdown (fallback)
<a name="aurora-analytics-table-scan-pushdown"></a>

Quando la query completa contiene costrutti che non possono essere trasferiti al motore analitico, Aurora PostgreSQL torna a inviare solo la scansione della tabella esterna. La scansione continua a ridurre le condizioni di filtro e le proiezioni di colonne supportate e il motore legge solo le colonne e le righe necessarie. I JOIN, gli ordinamenti e le operazioni non supportate vengono quindi eseguiti in PostgreSQL.

Vedi `Custom Scan` nodi annidati all'interno di nodi PostgreSQL standard:

```
EXPLAIN (COSTS OFF) SELECT ft.price, soundex(ft.mainroad)
FROM ft_house_price ft
LIMIT 5;
```

```
              QUERY PLAN
--------------------------------------
 Limit
   ->  Custom Scan on ft_house_price
         ->  READ_PARQUET
               Table: ft_house_price
               Projections: price, mainroad
```

`soundex()`Ecco una funzione PostgreSQL che non può essere trasferita al motore di analisi. Il motore legge le colonne (price, mainroad) in modo efficiente tramite READ\_PARQUET, quindi PostgreSQL si applica localmente. `soundex()`

## Lettura di un piano di esecuzione: procedura dettagliata
<a name="aurora-analytics-reading-plan-walkthrough"></a>

Gli esempi seguenti utilizzano piani di esecuzione reali da un set di dati TPC-H SF100 (\~34 GB Parquet) su un'istanza db.r8gd.8xlarge.

**Topics**
+ [Esempio 1: Interrogazione completa delle query (aggregazione con filtro)](#aurora-analytics-example-full-pushdown-aggregation)
+ [Esempio 2: Multi-table JOIN con pushdown completo](#aurora-analytics-example-multi-table-join)
+ [Esempio 3: Interruzione completa delle query con una tabella locale](#aurora-analytics-example-local-table)

### Esempio 1: Interrogazione completa delle query (aggregazione con filtro)
<a name="aurora-analytics-example-full-pushdown-aggregation"></a>

Questa è la TPC-H Query 1, una scansione, un filtro, un raggruppamento e un ordinamento su un'unica tabella di grandi dimensioni:

```
EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, BUFFERS OFF, SUMMARY OFF)
SELECT l_returnflag, l_linestatus, count(*), sum(l_quantity), avg(l_extendedprice)
FROM ft_lineitem
WHERE l_shipdate <= '1998-09-01'
GROUP BY l_returnflag, l_linestatus
ORDER BY l_returnflag, l_linestatus;
```

```
 Custom Scan (actual rows=4 loops=1)
   Output: aurora_analytics.l_returnflag, aurora_analytics.l_linestatus, aurora_analytics.count, ...
   Pushdown SQL: SELECT l_returnflag, l_linestatus, count(*) AS count, sum(l_quantity) AS sum,
     avg(l_extendedprice) AS avg FROM (SELECT l_quantity::DECIMAL(15,2) AS l_quantity,
     l_extendedprice::DECIMAL(15,2) AS l_extendedprice, l_returnflag::VARCHAR COLLATE "C" AS l_returnflag,
     l_linestatus::VARCHAR COLLATE "C" AS l_linestatus, l_shipdate::DATE AS l_shipdate
     FROM system.main.read_parquet($aurora_analytics_parameter_1) AS ft_lineitem) ft_lineitem
     WHERE (l_shipdate <= '1998-09-01'::DATE)
     GROUP BY l_returnflag, l_linestatus ORDER BY l_returnflag, l_linestatus
   ->  ORDER_BY (actual rows=4 loops=1)
         Order By: ft_lineitem.l_returnflag ASC, ft_lineitem.l_linestatus ASC
         ->  HASH_GROUP_BY (actual rows=4 loops=1)
               Groups: #0, #1
               Aggregates: count_star(), sum(#2), avg(#3)
               ->  PROJECTION (actual rows=591411581 loops=1)
                     Projections: l_returnflag, l_linestatus, l_quantity, l_extendedprice
                     ->  READ_PARQUET (actual rows=591411581 loops=1)
                           Table: ft_lineitem
                           Filters: l_shipdate<='1998-09-01'::DATE
                           Projections: l_quantity, l_extendedprice, l_returnflag, l_linestatus
                           Total Files Read: 21
                           Rows Removed by Filter: 15303257125
 Analytics Cache Hit Bytes: 4617440kB
 Analytics Remote Read Bytes: 16kB
 S3 HEAD Request Count: 0
 S3 GET Request Count: 2
```

**Leggendo questo piano dal basso verso l'alto:**

1. **READ\_PARQUET**: scansione di 21 file Parquet. `ft_lineitem` Il filtro `l_shipdate <= '1998-09-01'` è stato portato al livello di scansione (pressione dei predicati), saltando i gruppi di righe che non corrispondevano. «Righe rimosse dal filtro: 15.303.257.125" significa che miliardi di voci dei gruppi di righe sono state eliminate utilizzando le statistiche. min/max Sono state proiettate solo 4 colonne:,,,. `l_quantity` `l_extendedprice` `l_returnflag` `l_linestatus` Le altre 12 colonne lineitem non sono mai state lette da Amazon S3.

1. **PROIEZIONE**: sono state superate 591 milioni di righe qualificanti con le 4 colonne previste alla fase di aggregazione.

1. **HASH\_GROUP\_BY: raggruppato** per `l_returnflag` and `l_linestatus` (4 combinazioni distinte), calcolo e. `count(*)` `sum(l_quantity)` `avg(l_extendedprice)` 591 milioni di righe sono state ridotte a 4 righe di output.

1. **ORDER\_BY**: ha ordinato le 4 righe dei risultati per,. `l_returnflag` `l_linestatus`

1. **Scansione personalizzata (aurora\_analytics**): wrapper. Top-level Ha restituito 4 righe a PostgreSQL. La `Pushdown SQL` riga conferma che l'intera query è stata inviata al motore analitico.

**Cache e metriche S3:**
+ Accesso alla cache: \~4,5 GB (dati non disponibili, i dati sono stati memorizzati nella cache delle esecuzioni precedenti)
+ Lettura remota: 16 KB (quasi tutto fornito dalla cache)
+ 0 richieste HEAD, 2 richieste GET (attività minima di Amazon S3)
+ Quasi tutti i dati sono stati serviti dalla cache, con un'attività minima di Amazon S3

### Esempio 2: Multi-table JOIN con pushdown completo
<a name="aurora-analytics-example-multi-table-join"></a>

Questo è TPC-H Query 5, un join a 4 tabelle con filtro, aggregazione, ordinamento e limite:

```
EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, BUFFERS OFF, SUMMARY OFF)
SELECT n_name, count(*), sum(l_extendedprice * (1 - l_discount)) as revenue
FROM ft_lineitem
JOIN ft_orders ON l_orderkey = o_orderkey
JOIN ft_customer ON o_custkey = c_custkey
JOIN ft_nation ON c_nationkey = n_nationkey
WHERE o_orderdate >= '1994-01-01' AND o_orderdate < '1995-01-01'
GROUP BY n_name
ORDER BY revenue DESC
LIMIT 5;
```

```
 Custom Scan (actual rows=5 loops=1)
   Output: aurora_analytics.n_name, aurora_analytics.count, (aurora_analytics.revenue)::numeric
   Pushdown SQL: SELECT ft_nation.n_name, count(*) AS count,
     sum((ft_lineitem.l_extendedprice * ((1::INTEGER)::numeric - ft_lineitem.l_discount))) AS revenue
     FROM ((((SELECT ... FROM system.main.read_parquet($aurora_analytics_parameter_1) AS ft_lineitem) ...
     JOIN ... ft_orders ... JOIN ... ft_customer ... JOIN ... ft_nation ...)))
     WHERE ((ft_orders.o_orderdate >= '1994-01-01'::DATE) AND (ft_orders.o_orderdate < '1995-01-01'::DATE))
     GROUP BY ft_nation.n_name
     ORDER BY ... DESC LIMIT 5::INTEGER
   ->  TOP_N (actual rows=5 loops=1)
         Top: 5
         Order By: sum(...) DESC
         ->  HASH_GROUP_BY (actual rows=25 loops=1)
               Groups: #0
               Aggregates: count_star(), sum(#1)
               ->  PROJECTION (actual rows=91044214 loops=1)
                     Projections: n_name, (l_extendedprice * (1.000 - CAST(l_discount AS DECIMAL(18,3))))
                     ->  HASH_JOIN (actual rows=91044214 loops=1)
                           Join Type: INNER
                           Conditions: l_orderkey = o_orderkey
                           ->  READ_PARQUET (actual rows=92006243 loops=1)
                                 Table: ft_lineitem
                                 Projections: l_orderkey, l_extendedprice, l_discount
                                 Dynamic Filters: optional: l_orderkey>=5 AND l_orderkey<=599999975
                                   AND l_orderkey IN BF(o_orderkey)
                                 Total Files Read: 21
                                 Rows Removed by Filter: 15802662463
                           ->  HASH_JOIN (actual rows=22760819 loops=1)
                                 Join Type: INNER
                                 Conditions: c_custkey = o_custkey
                                 ->  HASH_JOIN (actual rows=10099742 loops=1)
                                       Join Type: INNER
                                       Conditions: c_nationkey = n_nationkey
                                       ->  READ_PARQUET (actual rows=10099742 loops=1)
                                             Table: ft_customer
                                             Projections: c_custkey, c_nationkey
                                             Dynamic Filters: optional: c_custkey>=1 AND c_custkey<=14999999
                                               AND c_custkey IN BF(o_custkey)
                                             Total Files Read: 2
                                             Rows Removed by Filter: 856257246
                                       ->  READ_PARQUET (actual rows=25 loops=1)
                                             Table: ft_nation
                                             Projections: n_nationkey, n_name
                                             Total Files Read: 1
                                 ->  READ_PARQUET (actual rows=22760819 loops=1)
                                       Table: ft_orders
                                       Filters: o_orderdate>='1994-01-01'::DATE AND o_orderdate<'1995-01-01'::DATE
                                       Projections: o_orderkey, o_custkey
                                       Total Files Read: 6
                                       Rows Removed by Filter: 4526635795
 Analytics Cache Hit Bytes: 3330521kB
 Analytics Remote Read Bytes: 2514317kB
 S3 HEAD Request Count: 0
 S3 GET Request Count: 4922
```

**Leggendo questo piano dal basso verso l'alto:**

1. **Quattro nodi READ\_PARQUET**: ogni tabella esterna viene scansionata in modo indipendente:
   + `ft_nation`: 25 righe da 1 file (tabella di piccole dimensioni)
   + `ft_customer`: 10 milioni di righe da 2 file, con eliminazione dinamica dei filtri in base agli ordini
   + `ft_orders`: 22,8 milioni di righe da 6 file, dopo il filtraggio fino al 1994 (4,5 miliardi di righe rimosse dal filtro della data)
   + `ft_lineitem`: 92 milioni di righe da 21 file, con il filtro Bloom premuto dal tasto orderjoin

1. **Tre nodi HASH\_JOIN**: il motore crea tabelle hash e si unisce nell'ordine:
   + nazione cliente (attivo) `c_nationkey = n_nationkey`
   + risultato ordini (attivi`o_custkey = c_custkey`)
   + risultato lineitem (on`l_orderkey = o_orderkey`)

1. **Filtri dinamici**: Aurora PostgreSQL passa i join key range e i filtri Bloom dal lato build alla scansione lato sonda. `l_orderkey IN BF(o_orderkey)`Ciò significa che vengono lette solo le righe lineitem che corrispondono alle chiavi degli ordini, un'ottimizzazione significativa.

1. **PROIEZIONE**: calcola 91 milioni di `l_extendedprice * (1 - l_discount)` righe unite.

1. **HASH\_GROUP\_BY: Raggruppa** per `n_name` (25 nazioni), riduce 91 milioni di righe a 25 gruppi.

1. **TOP\_N**: si colloca tra i primi 5 in termini di fatturato decrescente.

**Cache e metriche S3:**
+ Accesso alla cache: \~3,3 GB
+ Lettura remota: \~2,5 GB (copertura parziale della cache, alcuni dati sono ancora freddi)
+ 4.922 richieste S3 GET su 4 tabelle (30 file totali)
+ Confermato il pushdown completo delle interrogazioni: tutte e 4 le tabelle sono state unite all'interno del motore analitico

### Esempio 3: Interruzione completa delle query con una tabella locale
<a name="aurora-analytics-example-local-table"></a>

Una query ibrida che unisce una tabella esterna con una tabella PostgreSQL (heap) locale può essere completamente ridotta: il motore di analisi legge la tabella locale ed esegue autonomamente il join e l'aggregazione, purché la query utilizzi solo funzioni, tipi di dati e regole di confronto supportati. Nell'esempio seguente, una tabella heap locale `local_supp` è unita alla tabella esterna su chiavi intere: `ft_lineitem`

```
EXPLAIN (VERBOSE, COSTS OFF)
SELECT ls.s_regionkey, count(*)
FROM ft_lineitem
JOIN local_supp ls ON ft_lineitem.l_suppkey = ls.s_suppkey
WHERE l_shipdate > '1998-01-01'
GROUP BY ls.s_regionkey;
```

```
 Custom Scan
   Output: aurora_analytics.s_regionkey, aurora_analytics.count
   Pushdown SQL: SELECT ls.s_regionkey, count(*) AS count
     FROM ((SELECT l_suppkey::BIGINT AS l_suppkey, l_shipdate::DATE AS l_shipdate
            FROM system.main.read_parquet($aurora_analytics_parameter_1) AS ft_lineitem) ft_lineitem
       JOIN aurora_analytics.public.local_supp ls ON ((ft_lineitem.l_suppkey = ls.s_suppkey)))
     WHERE (ft_lineitem.l_shipdate > '1998-01-01'::DATE)
     GROUP BY ls.s_regionkey
   ->  HASH_GROUP_BY
         Groups: #0
         Aggregates: count_star()
         ->  PROJECTION
               Projections: s_regionkey
               ->  HASH_JOIN
                     Join Type: INNER
                     Conditions: l_suppkey = CAST(s_suppkey AS BIGINT)
                     ->  READ_PARQUET
                           Table: ft_lineitem
                           Filters: l_shipdate>'1998-01-01'::DATE
                           Projections: l_suppkey
                     ->  POSTGRES_SCAN
                           Table: local_supp
                           Projections: s_suppkey, s_regionkey
```

**Leggendo questo piano:**

1. **Singola scansione personalizzata di primo livello**: l'intera query, inclusa l'unione con la tabella locale, viene inviata al motore di analisi. Non ci sono nodi PostgreSQL HashAggregate (, Hash Join) che lo avvolgono, a differenza del precedente caso di pushdown table-scan.

1. **POSTGRES\_SCAN (local\_supp)**: la tabella heap locale viene letta dal motore di analisi stesso e inserita nel pushed-down. `HASH_JOIN` La tabella locale partecipa *all'unione all'interno* del motore anziché essere aggiunta successivamente da PostgreSQL.

1. **READ\_PARQUET (ft\_lineitem)**: La scansione della tabella esterna spinge solo il filtro e i progetti. `l_shipdate` `l_suppkey`

1. **HASH\_JOIN, HASH\_GROUP\_BY: L'aggregazione join e l'aggregazione**/vengono entrambe eseguite all'interno del motore. `GROUP BY` `count(*)`

**Aspetto fondamentale: l'unione di** una tabella esterna con una tabella locale non impone un fallback. Finché tutte le funzioni, i tipi di dati e le regole di confronto della query sono supportate, la tabella locale viene inserita nel motore di analisi e l'intera query viene ridotta.

L'unione di una tabella esterna con una tabella PostgreSQL locale non impedisce di per sé il pushdown completo. Il motore di analisi può inserire una tabella locale in un join premuto. Il pushdown completo viene impedito solo quando la query fa riferimento a qualcosa che il motore non può premere verso il basso, come una funzione, un tipo di dati o una collazione non supportati. Nell'esempio seguente, la colonna n\_name della tabella nazionale locale è character (25), un tipo non supportato, quindi Aurora PostgreSQL esegue solo la scansione della tabella esterna ed esegue il join in PostgreSQL:

```
EXPLAIN (VERBOSE, COSTS OFF)
SELECT n_name, count(*)
FROM ft_lineitem
JOIN nation ON ft_lineitem.l_suppkey = nation.n_nationkey
WHERE l_shipdate > '1998-01-01'
GROUP BY n_name;
```

```
 HashAggregate
   Output: nation.n_name, count(*)
   Group Key: nation.n_name
   ->  Hash Join
         Output: nation.n_name
         Hash Cond: (l_suppkey = nation.n_nationkey)
         ->  Custom Scan on public.ft_lineitem
               Output: l_orderkey, l_partkey, l_suppkey, ...
               Pushdown SQL: SELECT l_suppkey FROM (SELECT l_suppkey::BIGINT AS l_suppkey,
                 l_shipdate::DATE AS l_shipdate
                 FROM system.main.read_parquet($aurora_analytics_parameter_1) AS ft_lineitem)
                 ft_lineitem WHERE (l_shipdate > '1998-01-01'::DATE)
               ->  READ_PARQUET
                     Table: ft_lineitem
                     Filters: l_shipdate>'1998-01-01'::DATE
                     Projections: l_suppkey
         ->  Hash
               Output: nation.n_name, nation.n_nationkey
               ->  Seq Scan on public.nation
                     Output: nation.n_name, nation.n_nationkey
 Unsupported Pushdown Expressions:
 1: Type
    Description: character(25)
```

**Leggendo questo piano:**

1. **Struttura del piano**: a differenza degli esempi precedenti, questo piano prevede nodi PostgreSQL HashAggregate (, Hash Join, Seq Scan) che integrano la scansione personalizzata del motore di analisi. Si tratta di un pushdown basato su table-scan, non di un pushdown di query completo.

1. **Scansione personalizzata (ft\_lineitem):** Aurora PostgreSQL gestisce solo la scansione delle tabelle esterne. Aziona il `l_shipdate > '1998-01-01'` filtro e proietta solo un'efficiente scansione colonnare con previsione dei `l_suppkey` predicati.

1. **Seq Scan (nation)**: La `nation` tabella locale viene letta tramite l'esecutore standard di PostgreSQL (shared\_buffers → Aurora Storage).

1. **Hash Join**: PostgreSQL unisce i due set di risultati utilizzando un hash join attivo. `l_suppkey = n_nationkey`

1. **HashAggregate**: PostgreSQL esegue l'aggregazione GROUP BY e count (\*).

1. **Espressioni pushdown non supportate**: Il motivo per cui il pushdown completo non è riuscito: `character(25)` (il tipo di `n_name` colonna nella tabella locale). `nation` Il `char(n)` tipo non è supportato per il pushdown. Se questa tabella fosse una tabella esterna con `TEXT` colonne, il pushdown completo avrebbe esito positivo.

Conclusione **fondamentale:** nel pushdown table-scan, Aurora PostgreSQL offre ancora valore grazie a un'efficiente scansione colonnare con il pushdown dei predicati e l'eliminazione delle colonne. PostgreSQL gestisce solo le operazioni che non possono essere ridotte (funzioni, tipi di dati o regole di confronto non supportati). Se la tabella locale avesse utilizzato un tipo supportato, ad esempio `text` con un confronto compatibile, l'intero join ibrido sarebbe stato inviato al motore di analisi come un'unica scansione personalizzata.

## Utilizzo di EXPLAIN VERBOSE per visualizzare Pushdown SQL
<a name="aurora-analytics-explain-verbose"></a>

`EXPLAIN VERBOSE`rivela l'esatto codice SQL inviato al motore di analisi:

```
EXPLAIN (VERBOSE, COSTS OFF)
SELECT status, count(*), avg(total_amount)
FROM ft_orders
WHERE order_date > '2024-01-01'
GROUP BY status;
```

```
                              QUERY PLAN
------------------------------------------------------------------------
 Custom Scan
   Output: aurora_analytics.status, aurora_analytics.count, aurora_analytics.avg
   Pushdown SQL: SELECT status, count(*) AS count, avg(total_amount) AS avg
     FROM (SELECT status::VARCHAR COLLATE "C" AS status,
                  total_amount::DECIMAL(12,2) AS total_amount,
                  order_date::TIMESTAMP AS order_date
           FROM system.main.read_parquet($aurora_analytics_parameter_1) AS ft_orders)
     ft_orders WHERE (order_date > '2024-01-01'::TIMESTAMP)
     GROUP BY status
   ->  HASH_GROUP_BY
         Groups: #0
         Aggregates: count_star(), avg(#1)
         ->  READ_PARQUET
               Table: ft_orders
               Filters: order_date>'2024-01-01'
               Projections: status, total_amount, order_date
```

La `Pushdown SQL` riga mostra:
+ In che modo i tipi di PostgreSQL vengono convertiti ai tipi del motore analitico (ad esempio,) `status::VARCHAR COLLATE "C"`
+ Il riferimento al file parametrizzato () `$aurora_analytics_parameter_1`
+ Le esatte informazioni su WHERE, GROUP BY e le aggregazioni inserite nel motore

## Comprensione delle «espressioni pushdown non supportate»
<a name="aurora-analytics-unsupported-pushdown"></a>

Quando il pushdown completo della query fallisce, `EXPLAIN VERBOSE` riporta il **motivo** nella sezione «Espressioni pushdown non supportate». Questo indica quali costrutti hanno forzato il pushdown del fallback alla scansione delle tabelle:

```
EXPLAIN (VERBOSE, COSTS OFF)
SELECT soundex(name), age
FROM ft_passengers
LIMIT 5;
```

```
                              QUERY PLAN
------------------------------------------------------------------------
 Limit
   Output: (soundex(name)), age
   ->  Custom Scan on public.ft_passengers
         Output: soundex(name), age
         Pushdown SQL: SELECT name, age
           FROM (SELECT name::VARCHAR COLLATE "C" AS name,
                        age::DOUBLE AS age
                 FROM system.main.read_parquet($aurora_analytics_parameter_1)
                 AS ft_passengers) ft_passengers
         ->  READ_PARQUET
               Table: ft_passengers
               Projections: name, age
 Unsupported Pushdown Expressions:
 1: Function
    Description: soundex(text)
```

Il piano mostra:
+ **PostgreSQL gestisce la chiamata alla funzione and** `Limit` `soundex()`
+ **Aurora PostgreSQL gestisce solo la scansione della tabella** (lettura e colonne) `name` `age`
+ **Motivo: non** `soundex(text)` è una funzione sicura per il pushdown

**Topics**
+ [Categorie di espressioni non supportate](#aurora-analytics-unsupported-categories)

### Categorie di espressioni non supportate
<a name="aurora-analytics-unsupported-categories"></a>


| Categoria | Esempi | Come risolvere il problema | 
| --- | --- | --- | 
| Funzione | soundex(text),st\_makepoint(...), uuid\_generate\_v4() UDF | Riscrivi senza la funzione o accetta la funzione Table-Scan Pushdown | 
| Tipo | vector, calchi, bytea integer[] geometry | Usa i tipi supportati nelle espressioni | 
| Operatore | \~(regex), LIKE con regole di confronto non C, <\+> (pgvector) | Usa la collazione C o gli operatori predisposti per il pushdown | 
| Collation (Regola di confronto) | Non-C confronto su espressioni di confronto | Utilizzare COLLATE "C" in modo esplicito | 
| Aggregazione | percent\_rank(), array\_agg() | Riscrivi utilizzando gli aggregati supportati | 
| Sintassi SQL | ONLYparola chiave, elenco di obiettivi vuoto, CTE ricorsivi, mascheramento dinamico dei dati | Ristruttura la query | 

## Ottimizzazione delle query per un pushdown completo
<a name="aurora-analytics-tuning-pushdown"></a>

Per massimizzare le prestazioni, punta a un pushdown completo delle query. Utilizzalo `EXPLAIN VERBOSE` per controllare le tue query e correggere le espressioni non supportate:

**Fase 1: Controlla la tua richiesta**

```
EXPLAIN (VERBOSE, COSTS OFF) SELECT ... FROM ft_table ...;
```

Cerca «Unsupported Pushdown Expressions» nell'output.

**Fase 2: Identificare la causa**

Se presente, leggi la categoria e la descrizione per capire cosa ha impedito il pushdown completo.

**Fase 3: Correggi l'espressione**
+ **Funzione non supportata**: non esiste alcuna riscrittura che riduca una funzione non supportata. Quando una query applica una funzione non supportata (ad esempio`soundex()`) a una colonna di tabella esterna, Aurora PostgreSQL torna automaticamente al pushdown table-scan: invia comunque la scansione, la proiezione e tutti i filtri supportati al motore di analisi e applica la funzione in PostgreSQL alle righe restituite. Per ripristinare il pushdown completo, evita la funzione non supportata nelle query su tabelle esterne o precalcola il risultato nei dati di origine. Altrimenti, accettate il comando Table-Scan Pushdown, che garantisce comunque una scansione colonnare efficiente.
+ **Non-C collazione: aggiungi confronti espliciti ai confronti** testuali: `COLLATE "C"`

  ```
  -- Instead of:
  WHERE name LIKE 'Smith%'
  
  -- Use:
  WHERE name COLLATE "C" LIKE 'Smith%'
  ```
+ **Tipo non supportato**: evita il casting di tipi non supportati nelle espressioni su colonne di tabelle esterne.

**Fase 4: Verifica**

Dopo la correzione, riesegui `EXPLAIN VERBOSE` e conferma che «Unsupported Pushdown Expressions» è sparito.

## EXPLAIN, il riferimento alle metriche di
<a name="aurora-analytics-explain-analyze-metrics"></a>

Quando si utilizza`EXPLAIN ANALYZE`, alla fine dell'`EXPLAIN`output vengono visualizzati i seguenti parametri specifici per l'analisi, che riassumono l'attività di Amazon S3 e della cache per l'intera query. Ciascuno ha una metrica CloudWatch Amazon corrispondente a livello di istanza che puoi utilizzare per dashboard e allarmi tra le query:


| Metrica | Description | Metrica correlata | 
| --- | --- | --- | 
| Analytics Cache Hit Bytes | Dati forniti dalla cache locale su disco | AuroraAnalyticsCacheHit(Amazon CloudWatch, a livello di istanza) | 
| Analytics Remote Read Bytes | Dati recuperati da Amazon S3 (cache mancante) | AuroraAnalyticsRemoteRead(Amazon CloudWatch, a livello di istanza) | 
| S3 HEAD Request Count | Numero di richieste HEAD S3 (controlli dei metadati) | AuroraAnalyticsS3HeadRequest(Amazon CloudWatch, a livello di istanza) | 
| S3 GET Request Count | Numero di richieste S3 GET (recupero di dati) | AuroraAnalyticsS3GetRequest(Amazon CloudWatch, a livello di istanza) | 

Quando `aurora_analytics.track_detailed_metrics` è attivo, ogni `Custom Scan` nodo riporta anche le seguenti metriche di esecuzione per nodo:


| Metrica | Description | Metrica correlata | 
| --- | --- | --- | 
| Total CPU Time | Tempo di CPU impiegato dal motore di analisi durante l'esecuzione di questo nodo | vedere analytics\_total\_cpu\_time in aurora\_analytics\_stat\_statements() | 
| Effective Parallelism | Numero medio di thread di lavoro attivi durante l'esecuzione di questo nodo | AuroraAnalyticsActiveThreads(Amazon CloudWatch, a livello di istanza) | 
| Total Thread Wait Time | Tempo impiegato dai thread di lavoro del motore in attesa durante l'esecuzione di questo nodo | vedere analytics\_total\_thread\_wait\_time in aurora\_analytics\_stat\_statements() | 

## Suggerimenti per l'analisi del piano di esecuzione
<a name="aurora-analytics-tips"></a>
+ Usalo sempre `EXPLAIN VERBOSE` durante il debug del comportamento dei pushdown. Mostra entrambi e. `Pushdown SQL` `Unsupported Pushdown Expressions`
+ Un singolo `Custom Scan` al livello più alto del piano = pushdown completo (il più veloce). Un `Custom Scan` annidato all'interno dei nodi PostgreSQL (uno o più) = table-scan pushdown (più lento ma sfrutta comunque la scansione colonnare).
+ La `Filters` riga sottostante conferma che la clausola WHERE è stata spostata al livello di scansione`READ_PARQUET`. Se invece vedi `Filter:` a `Custom Scan` livello, il predicato non è stato spinto completamente verso il basso.
+ `Projections`sotto `READ_PARQUET` mostra quali colonne sono state lette da Parquet. Una query che proietta meno colonne legge meno dati. Evita `SELECT *` di usare tabelle esterne.
+ `Total Files Read`indica quanti file Parquet sono stati scansionati. Se questo valore vi sembra elevato, prendete in considerazione la possibilità di partizionare i dati.
+ `Rows Removed by Filter`mostra l'efficacia del predicate pushdown. Valori elevati indicano che il filtro funziona bene a livello di scansione.