

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

# IO: BufFileRead e IO: BufFileWrite
<a name="apg-waits.iobuffile"></a>

Gli eventi `IO:BufFileRead` e `IO:BufFileWrite` si verificano quando Aurora PostgreSQL crea file temporanei. Quando le operazioni richiedono più memoria rispetto ai parametri della memoria di lavoro attualmente definiti, scrivono dati temporanei sullo storage persistente. Questa operazione viene talvolta chiamata «*spilling to disk*». Per ulteriori informazioni sui file temporanei e sul loro utilizzo, consulta [Gestione dei file temporanei con PostgreSQL](PostgreSQL.ManagingTempFiles.md).

**Topics**
+ [

## Versioni del motore supportate
](#apg-waits.iobuffile.context.supported)
+ [

## Contesto
](#apg-waits.iobuffile.context)
+ [

## Probabili cause di aumento delle attese
](#apg-waits.iobuffile.causes)
+ [

## Azioni
](#apg-waits.iobuffile.actions)

## Versioni del motore supportate
<a name="apg-waits.iobuffile.context.supported"></a>

Queste informazioni relative all’evento di attesa sono supportate per tutte le versioni di Aurora PostgreSQL.

## Contesto
<a name="apg-waits.iobuffile.context"></a>

`IO:BufFileRead` e `IO:BufFileWrite` riguardano l'area di memoria di lavoro e l'area di memoria di lavoro di manutenzione. Per ulteriori informazioni su queste aree di memoria locale, consulta [Area di memoria di lavoro](AuroraPostgreSQL.Tuning.concepts.md#AuroraPostgreSQL.Tuning.concepts.local.work_mem) e [Area memoria di lavoro di manutenzione](AuroraPostgreSQL.Tuning.concepts.md#AuroraPostgreSQL.Tuning.concepts.local.maintenance_work_mem).

Il valore predefinito per `work_mem` è 4 MB. Se una sessione esegue operazioni in parallelo, ogni lavoratore che gestisce il parallelismo utilizza 4 MB di memoria. Per questo motivo, imposta `work_mem` con attenzione. Se si aumenta troppo il valore, un database che esegue molte sessioni potrebbe consumare troppa memoria. Se si imposta il valore troppo basso, Aurora PostgreSQL crea file temporanei nella memoria locale. Il disco I/O per questi file temporanei può ridurre le prestazioni.

Se si osserva la seguente sequenza di eventi, il database potrebbe generare file temporanei:

1. Riduzione improvvisa e brusca della disponibilità

1. Ripristino rapido per lo spazio libero

Potresti vedere anche un motivo a «motosega». Questo modello può indicare che il database sta creando costantemente file di piccole dimensioni.

## Probabili cause di aumento delle attese
<a name="apg-waits.iobuffile.causes"></a>

In generale, questi eventi di attesa sono causati da operazioni che consumano più memoria rispetto a quella allocata dai parametri `work_mem` o `maintenance_work_mem`. Per compensare, le operazioni scrivono su file temporanei. Cause comuni degli eventi `IO:BufFileRead` e `IO:BufFileWrite` includono quanto segue:

**Query che richiedono più memoria di quella esistente nell'area della memoria di lavoro**  
Le query con le seguenti caratteristiche utilizzano l'area di memoria di lavoro:  
+ Hash join
+ `ORDER BY`Clausola 
+ `GROUP BY`Clausola 
+ `DISTINCT`
+ Funzioni finestra
+ `CREATE TABLE AS SELECT`
+ Aggiornamento vista materializzata

**Istruzioni che richiedono più memoria di quella esistente nell'area della memoria di lavoro di manutenzione**  
Le istruzioni seguenti utilizzano l'area di memoria di lavoro di manutenzione:  
+ `CREATE INDEX`
+ `CLUSTER`

## Azioni
<a name="apg-waits.iobuffile.actions"></a>

Consigliamo azioni diverse a seconda delle cause dell’evento di attesa.

**Topics**
+ [

### Identificare il problema
](#apg-waits.iobuffile.actions.problem)
+ [

### Esamina le tue query di join
](#apg-waits.iobuffile.actions.joins)
+ [

### Esamina le query ORDER BY e GROUP BY
](#apg-waits.iobuffile.actions.order-by)
+ [

### Evitare di utilizzare l'operazione DISTINCT
](#apg-waits.iobuffile.actions.distinct)
+ [

### Considera l'utilizzo di funzioni finestra anziché le funzioni GROUP BY
](#apg-waits.iobuffile.actions.window)
+ [

### Indagare sulle viste materializzate e le istruzioni CTAS
](#apg-waits.iobuffile.actions.mv-refresh)
+ [

### Usa pg\$1repack quando crei indici
](#apg-waits.iobuffile.actions.pg_repack)
+ [

### Aumenta maintenance\$1work\$1mem quando esegui cluster
](#apg-waits.iobuffile.actions.cluster)
+ [

### Ottimizza la memoria per prevenire IO: BufFileRead e IO: BufFileWrite
](#apg-waits.iobuffile.actions.tuning-memory)

### Identificare il problema
<a name="apg-waits.iobuffile.actions.problem"></a>

È possibile visualizzare l'utilizzo dei file temporanei direttamente in Performance Insights. Per ulteriori informazioni, consulta [Visualizzazione dell’utilizzo dei file temporanei con Approfondimenti sulle prestazioni](PostgreSQL.ManagingTempFiles.Example.md). Quando Performance Insights è disabilitato, potresti notare un aumento `IO:BufFileRead` `IO:BufFileWrite` delle operazioni. Per risolvere i problemi, procedi come segue:

1. Esamina la `FreeLocalStorage` metrica in Amazon CloudWatch.

1. Cerca un motivo a motosega, che è una serie di punte frastagliate.

Un motivo a motosega indica un consumo e un rilascio rapido dello storage, spesso associato a file temporanei. Se noti questo modello, attiva Performance Insights. Quando si utilizza Performance Insights, è possibile identificare quando si verificano gli eventi di attesa e quali query sono associate. La soluzione dipende dalla query specifica che causa gli eventi.

Oppure, imposta il parametro `log_temp_files`. Questo parametro registra tutte le query che generano più della soglia KB di file temporanei. Se il valore è `0`, Aurora PostgreSQL registra tutti i file temporanei. Se il valore è `1024`, Aurora PostgreSQL registra tutte le query che producono file temporanei di dimensioni superiori a 1 MB. Per ulteriori informazioni su `log_temp_files`, consulta [Creazione di log e report di errore](https://www.postgresql.org/docs/10/runtime-config-logging.html) nella documentazione di PostgreSQL.

### Esamina le tue query di join
<a name="apg-waits.iobuffile.actions.joins"></a>

Probabilmente la tua applicazione usa join. Ad esempio, la seguente query unisce quattro tabelle.

```
SELECT * 
       FROM order 
 INNER JOIN order_item 
       ON (order.id = order_item.order_id)
 INNER JOIN customer 
       ON (customer.id = order.customer_id)
 INNER JOIN customer_address 
       ON (customer_address.customer_id = customer.id AND 
           order.customer_address_id = customer_address.id)
 WHERE customer.id = 1234567890;
```

Una possibile causa di picchi nell'utilizzo temporaneo dei file è un problema nella query stessa. Ad esempio, una clausola interrotta potrebbe non filtrare correttamente i join. Considera il secondo inner join nell'esempio seguente.

```
SELECT * 
       FROM order
 INNER JOIN order_item 
       ON (order.id = order_item.order_id)
 INNER JOIN customer 
       ON (customer.id = customer.id)
 INNER JOIN customer_address 
       ON (customer_address.customer_id = customer.id AND 
           order.customer_address_id = customer_address.id)
 WHERE customer.id = 1234567890;
```

La query precedente unisce erroneamente `customer.id` a `customer.id`, generando un prodotto cartesiano tra ogni cliente e ogni ordine. Questo tipo di join accidentale genera file temporanei di grandi dimensioni. A seconda delle dimensioni delle tabelle, una query cartesiana può anche riempire lo spazio di archiviazione. La domanda potrebbe avere join cartesiani quando vengono soddisfatte le seguenti condizioni:
+ Si notano forti e nitide riduzioni della disponibilità dello storage, seguite da un rapido ripristino.
+ Non sono in fase di creazione di indici.
+ Non vengono rilasciate istruzioni `CREATE TABLE FROM SELECT`.
+ Nessuna vista materializzata viene aggiornata.

Per verificare se le tabelle vengono unite utilizzando le chiavi appropriate, ispezionare le direttive di mappatura relazionale di query e oggetti. Tieni presente che alcune query della tua applicazione non vengono sempre chiamate e alcune query vengono generate dinamicamente.

### Esamina le query ORDER BY e GROUP BY
<a name="apg-waits.iobuffile.actions.order-by"></a>

In alcuni casi, una clausola `ORDER BY` può comportare file temporanei eccessivi. Considera le linee guida seguenti:
+ Includi solo colonne in una clausola `ORDER BY` quando devono essere ordinate. Questa linea guida è particolarmente importante per le query che restituiscono migliaia di righe e specificano molte colonne nella clausola `ORDER BY`.
+ Considerando la creazione di indici per accelerare clausole `ORDER BY` quando corrispondono a colonne che hanno lo stesso ordine crescente o decrescente. Gli indici parziali sono preferibili perché sono più piccoli. Gli indici più piccoli vengono letti e attraversati più rapidamente.
+ Se si creano indici per colonne che possono accettare valori nulli, considerare se si desidera che i valori nulli siano memorizzati alla fine o all'inizio degli indici.

  Se possibile, ridurre il numero di righe che devono essere ordinate filtrando il set di risultati. Se utilizzi istruzioni clausole o sottoquery `WITH`, ricorda che una query interna genera un set di risultati e lo passa alla query esterna. Maggiore è il numero di righe che una query può filtrare, minore è la necessità di ordinare la query.
+ Se non è necessario ottenere il set completo di risultati, utilizzare la clausola `LIMIT`. Ad esempio, se si desidera solo le prime cinque righe, una query che utilizza la clausola `LIMIT` non continua a generare risultati. In questo modo, la query richiede meno memoria e file temporanei.

Una query che utilizza una clausola `GROUP BY` può richiedere anche file temporanei. Le query `GROUP BY` riepilogano i valori utilizzando funzioni come le seguenti:
+ `COUNT`
+ `AVG`
+ `MIN`
+ `MAX`
+ `SUM`
+ `STDDEV`

Per sintonizzare le query `GROUP BY`, segui i consigli per le query `ORDER BY`.

### Evitare di utilizzare l'operazione DISTINCT
<a name="apg-waits.iobuffile.actions.distinct"></a>

Se possibile, evitare di utilizzare l’operazione `DISTINCT` per rimuovere righe duplicate. Più righe non necessarie e duplicate restituite dalla tua query, più costosa diventa l’operazione `DISTINCT`. Se possibile, aggiungi filtri nella clausola `WHERE` anche se utilizzi gli stessi filtri per tabelle diverse. Filtrare la query e unirsi correttamente migliora le prestazioni e riduce l'utilizzo delle risorse. Previene inoltre report e risultati errati.

Se devi usare `DISTINCT` per più righe di una stessa tabella, prendi in considerazione la possibilità di creare un indice composito. Il raggruppamento di più colonne in un indice può migliorare il tempo necessario per valutare righe distinte. Inoltre, se utilizzi Amazon Aurora PostgreSQL versione 10 o successiva, puoi correlare le statistiche tra più colonne utilizzando il comando `CREATE STATISTICS`.

### Considera l'utilizzo di funzioni finestra anziché le funzioni GROUP BY
<a name="apg-waits.iobuffile.actions.window"></a>

Utilizzando `GROUP BY` si modifica il set di risultati e quindi recupera il risultato aggregato. Utilizzando le funzioni della finestra, si aggregano i dati senza modificare il set di risultati. Una funzione finestra utilizza la clausola `OVER` per eseguire calcoli tra i set definiti dalla query, correlando una riga con un'altra. È possibile utilizzare tutte le funzioni `GROUP BY` nelle funzioni di finestra, ma anche funzioni come le seguenti:
+ `RANK`
+ `ARRAY_AGG`
+ `ROW_NUMBER`
+ `LAG`
+ `LEAD`

Per ridurre al minimo il numero di file temporanei generati da una funzione di finestra, rimuovere le duplicazioni per lo stesso set di risultati quando sono necessarie due aggregazioni distinte. Considera la query seguente.

```
SELECT sum(salary) OVER (PARTITION BY dept ORDER BY salary DESC) as sum_salary
     , avg(salary) OVER (PARTITION BY dept ORDER BY salary ASC) as avg_salary
  FROM empsalary;
```

È possibile riscrivere la query con la clausola `WINDOW` come segue.

```
SELECT sum(salary) OVER w as sum_salary
         , avg(salary) OVER w as_avg_salary
    FROM empsalary
  WINDOW w AS (PARTITION BY dept ORDER BY salary DESC);
```

Per impostazione predefinita, il planner di esecuzione Aurora PostgreSQL consolida nodi simili in modo da non duplicare le operazioni. Tuttavia, utilizzando una dichiarazione esplicita per il blocco finestra, è possibile mantenere la query più facilmente. È inoltre possibile migliorare le prestazioni impedendo la duplicazione.

### Indagare sulle viste materializzate e le istruzioni CTAS
<a name="apg-waits.iobuffile.actions.mv-refresh"></a>

Quando una vista materializzata si aggiorna, esegue una query. Questa query può contenere un'operazione come `GROUP BY`, `ORDER BY` oppure`DISTINCT`. Durante un aggiornamento, è possibile osservare un numero elevato di file temporanei e gli eventi di attesa `IO:BufFileWrite` e `IO:BufFileRead`. Allo stesso modo, quando crei una tabella basata su una dichiarazione `SELECT`, l'istruzione `CREATE TABLE` esegue una query. Per ridurre i file temporanei necessari, ottimizza la query.

### Usa pg\$1repack quando crei indici
<a name="apg-waits.iobuffile.actions.pg_repack"></a>

Quando crei un indice, il motore ordina il set di risultati. Man mano che le tabelle aumentano di dimensioni e man mano che i valori nella colonna indicizzata diventano più diversi, i file temporanei richiedono più spazio. Nella maggior parte dei casi, non è possibile impedire la creazione di file temporanei per tabelle di grandi dimensioni senza modificare l'area della memoria di lavoro di manutenzione. Per ulteriori informazioni, consulta [Area memoria di lavoro di manutenzione](AuroraPostgreSQL.Tuning.concepts.md#AuroraPostgreSQL.Tuning.concepts.local.maintenance_work_mem). 

Una possibile soluzione alternativa quando si ricrea un indice di grandi dimensioni consiste nell'utilizzare lo strumento pg\$1repack. Per ulteriori informazioni, consulta [Riorganizzare le tabelle nei database PostgreSQL con blocchi minimi](https://reorg.github.io/pg_repack/) nella documentazione di pg\$1repack.

### Aumenta maintenance\$1work\$1mem quando esegui cluster
<a name="apg-waits.iobuffile.actions.cluster"></a>

Il comando `CLUSTER` raggruppa la tabella specificata da *table\$1name* in base a un indice esistente specificato da *index\$1name*. Aurora PostgreSQL ricrea fisicamente la tabella in modo che corrisponda all'ordine di un determinato indice.

Quando lo storage magnetico era prevalente, il clustering era comune perché il throughput di storage era limitato. Ora che lo storage basato su SSD è comune, il clustering è meno popolare. Tuttavia, se si raggruppano le tabelle, è comunque possibile aumentare leggermente le prestazioni a seconda delle dimensioni della tabella, dell'indice, della query e così via. 

Se esegui il comando `CLUSTER` e osservi gli eventi di attesa `IO:BufFileWrite` e `IO:BufFileRead`, sintonizza `maintenance_work_mem`. Aumenta la dimensione della memoria a una quantità abbastanza grande. Un valore elevato significa che il motore può utilizzare più memoria per l'operazione di clustering.

### Ottimizza la memoria per prevenire IO: BufFileRead e IO: BufFileWrite
<a name="apg-waits.iobuffile.actions.tuning-memory"></a>

In alcune situazioni, è necessario sintonizzare la memoria. Il tuo obiettivo è quello di bilanciare i seguenti requisiti:
+ Il valore `work_mem` (vedi [Area di memoria di lavoro](AuroraPostgreSQL.Tuning.concepts.md#AuroraPostgreSQL.Tuning.concepts.local.work_mem))
+ La memoria rimanente dopo aver scontato il valore `shared_buffers` (vedi [Pool di buffer](AuroraMySQL.Managing.Tuning.concepts.md#AuroraMySQL.Managing.Tuning.concepts.memory.buffer-pool))
+ Le connessioni massime aperte e in uso, limitate da `max_connections`

#### Aumentare le dimensioni dell'area di memoria di lavoro
<a name="apg-waits.iobuffile.actions.tuning-memory.work-mem"></a>

In alcune situazioni, l'unica opzione è aumentare la memoria utilizzata dalla sessione. Se le tue query sono scritte correttamente e utilizzano i tasti corretti per i join, prendi in considerazione la possibilità di aumentare il valore `work_mem`. Per ulteriori informazioni, consulta [Area di memoria di lavoro](AuroraPostgreSQL.Tuning.concepts.md#AuroraPostgreSQL.Tuning.concepts.local.work_mem).

Per scoprire quanti file temporanei genera una query, imposta `log_temp_files` su `0`. Aumentando il valore `work_mem` al valore massimo identificato nei log, si impedisce alla query di generare file temporanei. Tuttavia, `work_mem` imposta il massimo per nodo piano per ogni connessione o operatore parallelo. Se il database ha 5.000 connessioni e se ciascuna utilizza una memoria di 256 MiB, il motore necessita di 1,2 TiB di RAM. Pertanto, la tua istanza potrebbe esaurirsi dalla memoria.

#### Riserva una memoria sufficiente per il buffer pool condiviso
<a name="apg-waits.iobuffile.actions.tuning-memory.shared-pool"></a>

Il database utilizza aree di memoria come il buffer pool condiviso, non solo l'area di memoria di lavoro. Considerare i requisiti di queste aree di memoria aggiuntive prima di aumentare `work_mem`. Per ulteriori informazioni sul pool di buffer, consulta [Pool di buffer](AuroraMySQL.Managing.Tuning.concepts.md#AuroraMySQL.Managing.Tuning.concepts.memory.buffer-pool).

Ad esempio, supponiamo che la classe di istanza Aurora PostgreSQL sia db.r5.2xlarge. Questa classe ha 64 GiB di memoria. Per impostazione predefinita, il 75% della memoria è riservato al buffer pool condiviso. Dopo aver sottratto la quantità allocata all'area di memoria condivisa, rimangono 16.384 MB. Non allocare la memoria rimanente esclusivamente all'area della memoria di lavoro perché anche il sistema operativo e il motore richiedono memoria.

La memoria a cui è possibile allocare per `work_mem` dipende dalla classe di istanza. Se si utilizza una classe di istanza più grande, è disponibile più memoria. Tuttavia, nell'esempio precedente, non è possibile utilizzare più di 16 GiB. In caso contrario, la tua istanza diventa non disponibile quando esaurisce la memoria. Per ripristinare l'istanza dallo stato non disponibile, i servizi di automazione Aurora PostgreSQL si riavviano automaticamente.

#### Gestisci il numero di connessioni
<a name="apg-waits.iobuffile.actions.tuning-memory.connections"></a>

Supponiamo che l'istanza del database disponga di 5.000 connessioni simultanee. Ogni connessione utilizza almeno 4 MiB di `work_mem`. L'elevato consumo di memoria delle connessioni rischia di peggiorare le prestazioni. Sono disponibili le seguenti opzioni:
+ Eseguire l'aggiornamento a una classe di istanza più grande
+ Diminuire il numero di connessioni simultanee al database utilizzando un proxy o un pool di connessioni.

Per i proxy, considera Amazon RDS Proxy, PGBouncer o un connection pooler basato sulla tua applicazione. Questa soluzione riduce il carico della CPU. Riduce inoltre il rischio quando tutte le connessioni richiedono l'area di memoria di lavoro. Quando esistono meno connessioni al database, è possibile aumentare il valore di `work_mem`. In questo modo, si riduce il verificarsi degli eventi di attesa `IO:BufFileRead` e `IO:BufFileWrite`. Inoltre, le query in attesa dell'area di memoria di lavoro accelerano in modo significativo.