

# Ajustar com eventos de espera do RDS para PostgreSQL
<a name="PostgreSQL.Tuning"></a>

Eventos de espera são uma ferramenta de ajuste importante do RDS para PostgreSQL. Se você puder descobrir por que as sessões estão aguardando recursos e o que elas estão fazendo, poderá reduzir melhor os gargalos. Use as informações nesta seção para encontrar possíveis causas e ações corretivas. Esta seção também aborda conceitos básicos de ajuste do PostgreSQL.

Os eventos de espera nesta seção são específicos do RDS para PostgreSQL.

**Topics**
+ [

# Conceitos essenciais para o ajuste do RDS para PostgreSQL
](PostgreSQL.Tuning.concepts.md)
+ [

# Eventos de espera do RDS para PostgreSQL
](PostgreSQL.Tuning.concepts.summary.md)
+ [

# Client:ClientRead
](wait-event.clientread.md)
+ [

# Client:ClientWrite
](wait-event.clientwrite.md)
+ [

# CPU
](wait-event.cpu.md)
+ [

# IO:BufFileRead and IO:BufFileWrite
](wait-event.iobuffile.md)
+ [

# IO:DataFileRead
](wait-event.iodatafileread.md)
+ [

# IO:WALWrite
](wait-event.iowalwrite.md)
+ [

# IPC: eventos de espera paralelos
](rpg-ipc-parallel.md)
+ [

# IPC:ProcArrayGroupUpdate
](apg-rpg-ipcprocarraygroup.md)
+ [

# Lock:advisory
](wait-event.lockadvisory.md)
+ [

# Lock:extend
](wait-event.lockextend.md)
+ [

# Lock:Relation
](wait-event.lockrelation.md)
+ [

# Lock:transactionid
](wait-event.locktransactionid.md)
+ [

# Lock:tuple
](wait-event.locktuple.md)
+ [

# LWLock:BufferMapping (LWLock:buffer\$1mapping)
](wait-event.lwl-buffer-mapping.md)
+ [

# LWLock:BufferIO (IPC:BufferIO)
](wait-event.lwlockbufferio.md)
+ [

# LWLock:buffer\$1content (BufferContent)
](wait-event.lwlockbuffercontent.md)
+ [

# LWLock:lock\$1manager (LWLock:lockmanager)
](wait-event.lw-lock-manager.md)
+ [

# LWLock:pg\$1stat\$1statements
](apg-rpg-lwlockpgstat.md)
+ [

# LWLock:SubtransSLRU (LWLock:SubtransControlLock)
](wait-event.lwlocksubtransslru.md)
+ [

# Tempo limite:PgSleep
](wait-event.timeoutpgsleep.md)
+ [

# Timeout:VacuumDelay
](wait-event.timeoutvacuumdelay.md)

# Conceitos essenciais para o ajuste do RDS para PostgreSQL
<a name="PostgreSQL.Tuning.concepts"></a>

Antes de ajustar seu banco de dados do RDS para PostgreSQL, aprenda o que são eventos de espera e por que eles ocorrem. Reveja também a arquitetura básica de memória e disco do RDS para PostgreSQL. Para obter um diagrama de arquitetura útil, consulte o wikibook [PostgreSQL](https://en.wikibooks.org/wiki/PostgreSQL/Architecture).

**Topics**
+ [

# Eventos de espera do RDS para PostgreSQL
](PostgreSQL.Tuning.concepts.waits.md)
+ [

# Memória do RDS para PostgreSQL
](PostgreSQL.Tuning.concepts.memory.md)
+ [

# Processo do RDS para PostgreSQL
](PostgreSQL.Tuning.concepts.processes.md)

# Eventos de espera do RDS para PostgreSQL
<a name="PostgreSQL.Tuning.concepts.waits"></a>

Um *evento de espera* é uma indicação de que a sessão está aguardando um recurso. Por exemplo, o evento de espera `Client:ClientRead` ocorre quando o RDS para PostgreSQL está aguardando para receber dados do cliente. Normalmente, as sessões aguardam por recursos como os seguintes.
+ Acesso com thread único a um buffer, por exemplo, quando uma sessão está tentando modificar um buffer
+ Uma linha que está bloqueada por outra sessão
+ Uma leitura de arquivo de dados
+ Uma gravação em arquivo de log

Por exemplo, para satisfazer uma consulta, a sessão pode realizar uma varredura de tabela completa. Se esses dados ainda não estiverem na memória, a sessão aguardará a conclusão da E/S do disco. Quando os buffers são lidos na memória, talvez a sessão precise aguardar, pois outras sessões estão acessando os mesmos buffers. O banco de dados registra as esperas utilizando um evento de espera predefinido. Esses eventos estão agrupados em categorias.

Por si só, um único evento de espera não indica um problema de performance. Por exemplo, se os dados solicitados não estão na memória, é necessário ler dados do disco. Se uma sessão bloquear uma linha para uma atualização, outra sessão aguardará que essa linha seja desbloqueada para poder atualizá-la. Uma confirmação exige a conclusão da gravação em um arquivo de log. Esperas são componentes integrais do funcionamento normal de um banco de dados. 

Por outro lado, uma série de eventos de espera geralmente mostra um problema de performance. Nesses casos, é possível utilizar os dados dos eventos de espera para determinar onde as sessões estão perdendo tempo. Por exemplo, se um relatório que é normalmente executado em minutos agora demora várias horas, é possível identificar os eventos de espera que mais contribuem para o tempo de espera total. Se você puder determinar as causas dos principais eventos de espera, às vezes pode aplicar alterações que melhoram a performance. Por exemplo, se a sua sessão está aguardando uma linha que foi bloqueada por outra sessão, é possível encerrar a sessão responsável pelo bloqueio. 

# Memória do RDS para PostgreSQL
<a name="PostgreSQL.Tuning.concepts.memory"></a>

A memória do RDS para PostgreSQL está dividida em compartilhada e local.

**Topics**
+ [

## Memória compartilhada no RDS para PostgreSQL
](#PostgreSQL.Tuning.concepts.shared)
+ [

## Memória local no RDS para PostgreSQL
](#PostgreSQL.Tuning.concepts.local)

## Memória compartilhada no RDS para PostgreSQL
<a name="PostgreSQL.Tuning.concepts.shared"></a>

O RDS para PostgreSQL aloca memória compartilhada quando a instância é iniciada. A memória compartilhada está dividida em várias subáreas. As seções a seguir fornecem descrições das mais importantes.

**Topics**
+ [

### Buffers compartilhados
](#PostgreSQL.Tuning.concepts.buffer-pool)
+ [

### Buffers de log de gravação antecipada (WAL)
](#PostgreSQL.Tuning.concepts.WAL)

### Buffers compartilhados
<a name="PostgreSQL.Tuning.concepts.buffer-pool"></a>

O *grupo de buffer compartilhado* é uma área de memória do RDS para PostgreSQL que contém todas as páginas que estão ou estavam sendo utilizadas por conexões de aplicações. Uma *página* é a versão de memória de um bloco de disco. O grupo de buffer compartilhado armazena em cache os blocos de dados lidos do disco. O grupo reduz a necessidade de reler dados do disco, fazendo com que o banco de dados opere de maneira mais eficiente.

Cada tabela e índice são armazenados como uma matriz de páginas com tamanho fixo. Cada bloco contém várias tuplas, que correspondem a linhas. Uma tupla pode ser armazenada em qualquer página.

O grupo de buffer compartilhado possui memória finita. Se uma nova solicitação exigir uma página que não esteja na memória e não houver mais memória, o RDS para PostgreSQL removerá uma página utilizada com menos frequência para acomodar essa solicitação. A política de despejo é implementada por um algoritmo de varredura de relógio.

O parâmetro `shared_buffers` determina a quantidade de memória que o servidor dedica ao armazenamento em cache de dados. O valor padrão é definido como `{DBInstanceClassMemory/32768}` bytes, com base na memória disponível para a instância de banco de dados.

### Buffers de log de gravação antecipada (WAL)
<a name="PostgreSQL.Tuning.concepts.WAL"></a>

Um *buffer de log de gravação antecipada (WAL)* mantém dados de transação que o RDS para PostgreSQL grava posteriormente no armazenamento persistente. Utilizando o mecanismo WAL, o RDS para PostgreSQL pode fazer o seguinte:
+ Recupere dados após uma falha
+ Reduzir a E/S de disco, evitando gravações frequentes em disco

Quando um cliente altera dados, o RDS para PostgreSQL grava as alterações no buffer de WAL. Quando o cliente emite um `COMMIT`, o processo gravador WAL grava dados de transação no arquivo de WAL.

O parâmetro `wal_level` determina quantas informações são gravadas no WAL, com valores possíveis como `minimal`, `replica` e `logical`.

## Memória local no RDS para PostgreSQL
<a name="PostgreSQL.Tuning.concepts.local"></a>

Todo processo de backend aloca memória local para processamento de consultas.

**Topics**
+ [

### Área de memória de trabalho
](#PostgreSQL.Tuning.concepts.local.work_mem)
+ [

### Área de memória de trabalho para manutenção
](#PostgreSQL.Tuning.concepts.local.maintenance_work_mem)
+ [

### Área de buffer temporária
](#PostgreSQL.Tuning.concepts.temp)

### Área de memória de trabalho
<a name="PostgreSQL.Tuning.concepts.local.work_mem"></a>

A *área de memória de trabalho*contém dados temporários para consultas que executam classificações e hashes. Por exemplo, uma consulta com uma cláusula `ORDER BY` executa uma classificação. Consultas usam tabelas de hash em agregações e junções de hash.

O parâmetro `work_mem` é a quantidade de memória a ser utilizada por operações de classificação internas e tabelas de hash antes da gravação em arquivos de disco temporários, o que é medido em megabytes. O valor padrão é 4 MB. Várias sessões podem ser executadas simultaneamente, e cada uma pode executar operações de manutenção em paralelo. Por esse motivo, a memória de trabalho total utilizada pode ser múltiplos da configuração `work_mem`. 

### Área de memória de trabalho para manutenção
<a name="PostgreSQL.Tuning.concepts.local.maintenance_work_mem"></a>

A *área de memória de trabalho para manutenção* armazena dados em cache para operações de manutenção. Essas operações incluem aspiração, criação de índices e adição de chaves externas.

O parâmetro `maintenance_work_mem` especifica a quantidade máxima de memória a ser utilizada por operações de manutenção, o que é medido em megabytes. O valor padrão é 64 MB. Uma sessão de banco de dados apenas pode executar uma operação de manutenção de cada vez.

### Área de buffer temporária
<a name="PostgreSQL.Tuning.concepts.temp"></a>

A *área de buffer temporária* armazena tabelas temporárias em cache para cada sessão de banco de dados.

Cada sessão aloca buffers temporários conforme necessário até o limite especificado. Quando a sessão termina, o servidor limpa os buffers.

O parâmetro `temp_buffers` define o número máximo de buffers temporários utilizados por cada sessão, o que é medido em megabytes. O valor padrão é de 8 MB. Antes do primeiro uso de tabelas temporárias em uma sessão, é possível alterar o valor de `temp_buffers`.

# Processo do RDS para PostgreSQL
<a name="PostgreSQL.Tuning.concepts.processes"></a>

O RDS para PostgreSQL utiliza vários processos.

**Topics**
+ [

## Processo Postmaster
](#PostgreSQL.Tuning.concepts.postmaster)
+ [

## Processos de backend
](#PostgreSQL.Tuning.concepts.backend)
+ [

## Processos em segundo plano
](#PostgreSQL.Tuning.concepts.vacuum)

## Processo Postmaster
<a name="PostgreSQL.Tuning.concepts.postmaster"></a>

O *processo de postmaster* é o primeiro a ser iniciado quando você inicia o RDS para PostgreSQL. Ele tem as seguintes responsabilidades principais:
+ Bifurcar e monitorar processos em segundo plano
+ Receba solicitações de autenticação dos processos do cliente e autentique-as antes de permitir que o banco de dados atenda às solicitações

## Processos de backend
<a name="PostgreSQL.Tuning.concepts.backend"></a>

Se o postmaster autenticar uma solicitação de cliente, o postmaster bifurcará um novo processo de backend, também chamado de processo postgres. Um processo de cliente conecta-se exatamente a um processo de backend. O processo de cliente e o processo de backend se comunicam diretamente sem a intervenção do processo postmaster.

## Processos em segundo plano
<a name="PostgreSQL.Tuning.concepts.vacuum"></a>

O processo postmaster bifurca vários processos que realizam diferentes tarefas de backend. Alguns dos mais importantes incluem:
+ Gravador WAL

  O RDS para PostgreSQL grava dados no buffer de WAL (gravação antecipada) nos arquivos de log. O princípio do registro em log de gravação antecipada determina que o banco de dados não pode gravar alterações nos arquivos de dados até que o banco de dados grave registros de log descrevendo essas alterações no disco. O mecanismo WAL reduz a E/S do disco e permite que o RDS para PostgreSQL utilize os logs para recuperar o banco de dados após uma falha.
+ Gravador em segundo plano

  Esse processo grava periodicamente páginas sujas (modificadas) dos buffers de memória nos arquivos de dados. Uma página fica suja quando um processo de backend a modifica na memória.
+ Daemon autovacuum

  O daemon consiste no seguinte:
  + O launcher de autovacuum
  + Os processos de operador de autovacuum

  Quando o autovacuum está ativado, ele procura tabelas que tiveram um grande número de tuplas inseridas, atualizadas ou excluídas. Esse daemon tem as seguintes responsabilidades:
  + Recuperar ou reutilizar o espaço em disco ocupado por linhas atualizadas ou excluídas
  + Atualizar estatísticas utilizadas pelo planejador
  + Proteger contra a perda de dados antigos devido à recorrência de IDs de transação

  O recurso e autovacuum automatiza a execução de comandos `VACUUM` e `ANALYZE`. `VACUUM` tem as seguintes variantes: padrão e completo. O vacuum padrão é executado em paralelo com outras operações de banco de dados. `VACUUM FULL` requer um bloqueio exclusivo na tabela em que está trabalhando. Portanto, ele não pode ser executado em paralelo com operações que acessam a mesma tabela. `VACUUM` cria uma quantidade substancial de tráfego de E/S, podendo piorar a performance para outras sessões ativas.

# Eventos de espera do RDS para PostgreSQL
<a name="PostgreSQL.Tuning.concepts.summary"></a>

A tabela a seguir lista os eventos de espera do RDS para PostgreSQL que indicam mais comumente problemas de performance e resume as causas e as medidas corretivas mais comuns.


| Eventos de espera | Definição | 
| --- | --- | 
|  [Client:ClientRead](wait-event.clientread.md)  |  Esse evento ocorre quando o RDS para PostgreSQL está aguardando para receber dados do cliente.  | 
|  [Client:ClientWrite](wait-event.clientwrite.md)  |  Esse evento ocorre quando o RDS para PostgreSQL está aguardando para gravar dados no cliente.  | 
|  [CPU](wait-event.cpu.md)  | Ocorre quando um thread está ativo na CPU ou está aguardando a CPU.  | 
|  [IO:BufFileRead and IO:BufFileWrite](wait-event.iobuffile.md)  |  Esses eventos ocorrem quando o RDS para PostgreSQL cria arquivos temporários.  | 
|  [IO:DataFileRead](wait-event.iodatafileread.md)  |  Esse evento ocorre quando uma conexão aguarda em um processo de backend para ler uma página necessária do armazenamento porque essa página não está disponível na memória compartilhada.   | 
| [IO:WALWrite](wait-event.iowalwrite.md)  | Esse evento ocorre quando o RDS para PostgreSQL está aguardando os buffers do log de gravação antecipada (WAL) serem gravados em um arquivo WAL.  | 
|  [Lock:advisory](wait-event.lockadvisory.md)  |  Esse evento ocorre quando uma aplicação PostgreSQL utiliza um bloqueio para coordenar as atividades em várias sessões.  | 
|  [Lock:extend](wait-event.lockextend.md) |  Esse evento ocorre quando um processo de backend está aguardando para bloquear uma relação com o objetivo de a estender, enquanto outro processo tem um bloqueio nessa relação para o mesmo objetivo.  | 
|  [Lock:Relation](wait-event.lockrelation.md)  |  Esse evento ocorre quando uma consulta está aguardando para adquirir um bloqueio em uma tabela ou visualização que está atualmente bloqueada por outra transação.  | 
|  [Lock:transactionid](wait-event.locktransactionid.md)  | Esse evento ocorre quando uma transação está aguardando um bloqueio em nível de linha. | 
|  [Lock:tuple](wait-event.locktuple.md)  |  Esse evento ocorre quando um processo de backend está aguardando para adquirir um bloqueio em uma tupla.  | 
|  [LWLock:BufferMapping (LWLock:buffer\$1mapping)](wait-event.lwl-buffer-mapping.md)  |  Esse evento ocorre quando uma sessão está aguardando para associar um bloco de dados a um buffer no grupo de buffer compartilhado.  | 
|  [LWLock:BufferIO (IPC:BufferIO)](wait-event.lwlockbufferio.md)  |  Esse evento ocorre quando o RDS para PostgreSQL está aguardando que outros processos terminem suas operações de entrada/saída (E/S) ao tentarem acessar simultaneamente uma página.  | 
|  [LWLock:buffer\$1content (BufferContent)](wait-event.lwlockbuffercontent.md)  |  Esse evento ocorre quando uma sessão aguarda para ler ou gravar uma página de dados na memória enquanto outra sessão fica com a página bloqueada para gravação.  | 
|  [LWLock:lock\$1manager (LWLock:lockmanager)](wait-event.lw-lock-manager.md)  | Esse evento ocorre quando o mecanismo do RDS para PostgreSQL mantém a área de memória do bloqueio compartilhado para alocar, conferir e desalocar um bloqueio nos casos em que um bloqueio de caminho rápido não é possível. | 
|  [LWLock:SubtransSLRU (LWLock:SubtransControlLock)](wait-event.lwlocksubtransslru.md)  |  Esse evento ocorre quando um processo está aguardando para acessar o cache simples menos recentemente utilizado (SLRU) para uma subtransação.  | 
|  [Tempo limite:PgSleep](wait-event.timeoutpgsleep.md)  |  Esse evento ocorre quando um processo do servidor chama a função `pg_sleep` e está aguardando o tempo limite de suspensão expirar.   | 
|  [Timeout:VacuumDelay](wait-event.timeoutvacuumdelay.md)  | Esse evento indica que o processo de vácuo está inativo porque o limite de custo estimado foi atingido.  | 

# Client:ClientRead
<a name="wait-event.clientread"></a>

O evento `Client:ClientRead` ocorre quando o RDS para PostgreSQL está aguardando receber dados do cliente.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.clientread.context.supported)
+ [

## Contexto
](#wait-event.clientread.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.clientread.causes)
+ [

## Ações
](#wait-event.clientread.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.clientread.context.supported"></a>

Essas informações sobre eventos de espera são compatíveis com o RDS para PostgreSQL versão 10 e superiores.

## Contexto
<a name="wait-event.clientread.context"></a>

Uma instância de banco de dados do RDS para PostgreSQL está aguardando para receber dados do cliente. A instância de banco de dados do RDS para PostgreSQL deve receber os dados do cliente para poder enviar mais dados ao cliente. O tempo de espera da instância antes de receber dados do cliente é um evento `Client:ClientRead`.

## Possíveis causas do maior número de esperas
<a name="wait-event.clientread.causes"></a>

Causas comuns do surgimento do evento `Client:ClientRead` nas principais esperas incluem: 

**Maior latência de rede**  
Pode haver maior latência de rede entre a instância de banco de dados do RDS para PostgreSQL e o cliente. A latência de rede mais alta aumenta o tempo necessário para a instância de banco de dados receber dados do cliente.

**Maior carga no cliente**  
Pode haver pressão da CPU ou saturação da rede no lado do cliente. Um aumento na carga no cliente pode atrasar a transmissão de dados do cliente para a instância de banco de dados do RDS para PostgreSQL.

**Excesso de viagens de ida e volta na rede**  
Um número elevado de viagens de ida e volta na rede entre a instância de banco de dados do RDS para PostgreSQL e o cliente pode atrasar a transmissão de dados do cliente para a instância do RDS para PostgreSQL.

**Operação de cópia extensa**  
Durante uma operação de cópia, os dados são transferidos do sistema de arquivos do cliente para a instância de banco de dados do RDS para PostgreSQL. O envio de uma muitos dados para a instância de banco de dados pode atrasar a transmissão de dados do cliente para a instância de banco de dados.

**Desconexão de um cliente inativo**  
Quando um cliente se conecta à instância de banco de dados do RDS para PostgreSQL em um estado `idle in transaction`, a instância de banco de dados pode esperar que o cliente envie mais dados ou emitir um comando. Uma conexão nesse estado pode resultar no aumento de eventos `Client:ClientRead`.

**PgBouncer utilizado para agrupamento de conexões**  
PgBouncer tem uma configuração de rede de baixo nível chamada `pkt_buf` e que está definida como 4.096 por padrão. Se a workload estiver enviando pacotes de consulta maiores que 4.096 bytes por meio de PgBouncer, convém aumentar a configuração `pkt_buf` para 8.192. Se a nova configuração não diminuir o número de eventos `Client:ClientRead`, convém aumentar a configuração `pkt_buf` para valores maiores, como 16.384 ou 32.768. Se o texto da consulta for grande, a configuração maior pode ser particularmente útil.

## Ações
<a name="wait-event.clientread.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera.

**Topics**
+ [

### Colocar os clientes na mesma zona de disponibilidade e sub-rede da VPC que a instância
](#wait-event.clientread.actions.az-vpc-subnet)
+ [

### Escalar seu cliente
](#wait-event.clientread.actions.scale-client)
+ [

### Utilizar instâncias da geração atual
](#wait-event.clientread.actions.db-instance-class)
+ [

### Aumentar a largura de banda da rede
](#wait-event.clientread.actions.increase-network-bandwidth)
+ [

### Monitorar máximos de performance da rede
](#wait-event.clientread.actions.monitor-network-performance)
+ [

### Monitorar transações no estado de “inatividade em transação”
](#wait-event.clientread.actions.check-idle-in-transaction)

### Colocar os clientes na mesma zona de disponibilidade e sub-rede da VPC que a instância
<a name="wait-event.clientread.actions.az-vpc-subnet"></a>

Para reduzir a latência e aumentar o throughput da rede, coloque clientes na mesma zona de disponibilidade e na mesma sub-rede de nuvem privada virtual (VPC) que a instância de banco de dados do RDS para PostgreSQL. Os clientes devem estar o mais próximos possível da instância de banco de dados.

### Escalar seu cliente
<a name="wait-event.clientread.actions.scale-client"></a>

Utilizando o Amazon CloudWatch ou outras métricas de host, determine se o cliente está atualmente restrito pela CPU ou pela largura de banda da rede, ou por ambas. Se o cliente estiver restrito, escale-o de acordo.

### Utilizar instâncias da geração atual
<a name="wait-event.clientread.actions.db-instance-class"></a>

Em alguns casos, talvez você não esteja utilizando uma classe de instância de banco de dados que ofereça suporte a quadros jumbo. Se estiver executando sua aplicação no Amazon EC2, considere utilizar uma instância de geração atual para o cliente. Além disso, configure a MTU (unidade de transmissão máxima) no sistema operacional cliente. Essa técnica pode reduzir o número de idas e voltas pela rede e aumentar a taxa de transferência da rede. Consulte mais informações em [Frames jumbo (9001 MTU)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances) no *Guia do usuário do Amazon EC2*.

Para obter informações sobre classes de instância de banco de dados, consulte [Classes de instâncias de banco de dados do ](Concepts.DBInstanceClass.md). Para determinar a classe de instância de banco de dados equivalente a um tipo de instância do Amazon EC2, coloque `db.` antes do nome do tipo de instância do Amazon EC2. Por exemplo, a instância `r5.8xlarge` do Amazon EC2 é equivalente à classe de instância de banco de dados `db.r5.8xlarge`.

### Aumentar a largura de banda da rede
<a name="wait-event.clientread.actions.increase-network-bandwidth"></a>

Utilize as métricas `NetworkReceiveThroughput` e `NetworkTransmitThroughput` do Amazon CloudWatch para monitorar o tráfego de rede de entrada e saída na instância de banco de dados. Essas métricas podem ajudar você a determinar se a largura de banda da rede é suficiente para a sua workload. 

Se a largura de banda da rede não suficiente, aumente-a. Se o cliente AWS ou sua instância de banco de dados estiver atingindo os limites de largura de banda da rede, a única maneira de aumentar a largura de banda será ampliar o tamanho da instância de banco de dados. Para obter mais informações, consulte [Tipos de classe de instância de banco de dados](Concepts.DBInstanceClass.Types.md).

Para ter mais informações sobre métricas do CloudWatch, consulte [Métricas do Amazon CloudWatch para o Amazon RDS](rds-metrics.md). 

### Monitorar máximos de performance da rede
<a name="wait-event.clientread.actions.monitor-network-performance"></a>

Se você utiliza clientes do Amazon EC2, o Amazon EC2 fornece máximos para métricas de performance da rede, incluindo largura de banda de rede agregada de entrada e saída. Ele também fornece rastreamento de conexões para garantir que os pacotes sejam retornados conforme esperado e vinculem localmente o acesso para serviços como o Sistema de Nomes de Domínio (DNS). Para monitorar esses máximos, utilize um driver de rede avançado atual e monitore a performance de rede do seu cliente. 

Consulte mais informações em [Monitorar a performance de rede de sua instância do EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) no *Guia do usuário do Amazon EC2*.

### Monitorar transações no estado de “inatividade em transação”
<a name="wait-event.clientread.actions.check-idle-in-transaction"></a>

Verifique se você tem um número cada vez maior de conexões `idle in transaction`. Para isso, monitore a coluna `state` na tabela `pg_stat_activity`. Talvez seja possível identificar a origem da conexão executando uma consulta semelhante à seguinte.

```
select client_addr, state, count(1) from pg_stat_activity 
where state like 'idle in transaction%' 
group by 1,2 
order by 3 desc
```

# Client:ClientWrite
<a name="wait-event.clientwrite"></a>

O evento `Client:ClientWrite` ocorre quando o RDS para PostgreSQL está aguardando para gravar dados no cliente.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.clientwrite.context.supported)
+ [

## Contexto
](#wait-event.clientwrite.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.clientwrite.causes)
+ [

## Ações
](#wait-event.clientwrite.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.clientwrite.context.supported"></a>

Essas informações sobre eventos de espera são compatíveis com o RDS para PostgreSQL versão 10 e superiores.

## Contexto
<a name="wait-event.clientwrite.context"></a>

Um processo de cliente deve ler todos os dados recebidos de um cluster de banco de dados do RDS para PostgreSQL para que o cluster possa enviar mais dados. O tempo de espera do cluster antes de enviar mais dados ao cliente é um evento `Client:ClientWrite`.

O throughput reduzido da rede entre a instância de banco de dados do RDS para PostgreSQL e o cliente pode causar esse evento. A pressão da CPU e a saturação da rede no cliente também podem causar esse evento. *Pressão da CPU* é quando a CPU está totalmente utilizada e existem tarefas aguardando o tempo da CPU. *Saturação de rede* é quando a rede entre o banco de dados e o cliente está transportando mais dados do que ela pode manipular. 

## Possíveis causas do maior número de esperas
<a name="wait-event.clientwrite.causes"></a>

Causas comuns do surgimento do evento `Client:ClientWrite` nas principais esperas incluem: 

**Maior latência de rede**  
Pode haver maior latência de rede entre a instância de banco de dados do RDS para PostgreSQL e o cliente. A latência de rede mais alta aumenta o tempo necessário para o cliente receber os dados.

**Maior carga no cliente**  
Pode haver pressão da CPU ou saturação da rede no lado do cliente. Um aumento na carga do cliente atrasa o recebimento de dados da instância de banco de dados do RDS para PostgreSQL.

**Grande volume de dados enviados ao cliente**  
A instância de banco de dados do RDS para PostgreSQL pode estar enviando uma grande quantidade de dados ao cliente. É possível que um cliente não consiga receber os dados tão rápido quanto o cluster os está enviando. Atividades como cópias de tabelas grandes podem resultar no aumento de eventos `Client:ClientWrite`.

## Ações
<a name="wait-event.clientwrite.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera.

**Topics**
+ [

### Colocar os clientes na mesma zona de disponibilidade e sub-rede VPC que o cluster
](#wait-event.clientwrite.actions.az-vpc-subnet)
+ [

### Utilizar instâncias da geração atual
](#wait-event.clientwrite.actions.db-instance-class)
+ [

### Reduzir a quantidade de dados enviados ao cliente
](#wait-event.clientwrite.actions.reduce-data)
+ [

### Escalar seu cliente
](#wait-event.clientwrite.actions.scale-client)

### Colocar os clientes na mesma zona de disponibilidade e sub-rede VPC que o cluster
<a name="wait-event.clientwrite.actions.az-vpc-subnet"></a>

Para reduzir a latência e aumentar o throughput da rede, coloque clientes na mesma zona de disponibilidade e na mesma sub-rede de nuvem privada virtual (VPC) que a instância de banco de dados do RDS para PostgreSQL.

### Utilizar instâncias da geração atual
<a name="wait-event.clientwrite.actions.db-instance-class"></a>

Em alguns casos, talvez você não esteja utilizando uma classe de instância de banco de dados que ofereça suporte a quadros jumbo. Se estiver executando sua aplicação no Amazon EC2, considere utilizar uma instância de geração atual para o cliente. Além disso, configure a MTU (unidade de transmissão máxima) no sistema operacional cliente. Essa técnica pode reduzir o número de idas e voltas pela rede e aumentar a taxa de transferência da rede. Consulte mais informações em [Frames jumbo (9001 MTU)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances) no *Guia do usuário do Amazon EC2*.

Para obter informações sobre classes de instância de banco de dados, consulte [Classes de instâncias de banco de dados do ](Concepts.DBInstanceClass.md). Para determinar a classe de instância de banco de dados equivalente a um tipo de instância do Amazon EC2, coloque `db.` antes do nome do tipo de instância do Amazon EC2. Por exemplo, a instância `r5.8xlarge` do Amazon EC2 é equivalente à classe de instância de banco de dados `db.r5.8xlarge`.

### Reduzir a quantidade de dados enviados ao cliente
<a name="wait-event.clientwrite.actions.reduce-data"></a>

Quando possível, ajuste a aplicação para reduzir a quantidade de dados que a instância de banco de dados do RDS para PostgreSQL envia ao cliente. Fazer esses ajustes alivia a contenção da CPU e da rede no lado do cliente.

### Escalar seu cliente
<a name="wait-event.clientwrite.actions.scale-client"></a>

Utilizando o Amazon CloudWatch ou outras métricas de host, determine se o cliente está atualmente restrito pela CPU ou pela largura de banda da rede, ou por ambas. Se o cliente estiver restrito, escale-o de acordo.

# CPU
<a name="wait-event.cpu"></a>

Ocorre quando um thread está ativo na CPU ou está aguardando a CPU.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.cpu.context.supported)
+ [

## Contexto
](#wait-event.cpu.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.cpu.causes)
+ [

## Ações
](#wait-event.cpu.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.cpu.context.supported"></a>

Essas informações de evento de espera são relevantes para todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.cpu.context"></a>

A *unidade de processamento central (CPU)* é o componente de um computador que executa instruções. Por exemplo, instruções de CPU realizam operações aritméticas e trocam dados na memória. Se uma consulta aumentar o número de instruções que ela executa por meio do mecanismo de banco de dados, o tempo gasto na execução dessa consulta aumentará. *Programação da CPU* refere-se a alocar tempo de CPU a um processo. A programação é orquestrada pelo kernel do sistema operacional.

**Topics**
+ [

### Como saber quando essa espera ocorre
](#wait-event.cpu.when-it-occurs)
+ [

### Métrica DBLoadCPU
](#wait-event.cpu.context.dbloadcpu)
+ [

### Métricas os.cpuUtilization
](#wait-event.cpu.context.osmetrics)
+ [

### Provável causa da programação da CPU
](#wait-event.cpu.context.scheduling)

### Como saber quando essa espera ocorre
<a name="wait-event.cpu.when-it-occurs"></a>

Esse evento de espera `CPU` indica que um processo de backend está ativo na CPU ou aguardando a CPU. É possível determinar que isso está ocorrendo quando uma consulta mostra as seguintes informações:
+ A coluna `pg_stat_activity.state` tem o valor `active`.
+ As colunas `wait_event_type` e `wait_event` em `pg_stat_activity` são ambas `null`.

Para ver os processos de backend que estão utilizando ou aguardando CPU, execute a seguinte consulta.

```
SELECT * 
FROM   pg_stat_activity
WHERE  state = 'active'
AND    wait_event_type IS NULL
AND    wait_event IS NULL;
```

### Métrica DBLoadCPU
<a name="wait-event.cpu.context.dbloadcpu"></a>

A métrica do Performance Insights para CPU é `DBLoadCPU`. O valor de `DBLoadCPU` pode diferir do valor da métrica `CPUUtilization` do Amazon CloudWatch. A última métrica é coletada do HyperVisor para uma instância de banco de dados.

### Métricas os.cpuUtilization
<a name="wait-event.cpu.context.osmetrics"></a>

As métricas do Performance Insights para o sistema operacional fornecem informações detalhadas sobre a utilização da CPU. Por exemplo, é possível exibir as seguintes métricas:
+ `os.cpuUtilization.nice.avg`
+ `os.cpuUtilization.total.avg`
+ `os.cpuUtilization.wait.avg`
+ `os.cpuUtilization.idle.avg`

O Performance Insights relata o uso da CPU pelo mecanismo de banco de dados como `os.cpuUtilization.nice.avg`.

### Provável causa da programação da CPU
<a name="wait-event.cpu.context.scheduling"></a>

 O kernel do sistema operacional (SO) lida com agendamento para a CPU. Quando a CPU está *ativa*, talvez um processo precise esperar para ser agendado. A CPU está ativa enquanto executa cálculos. Também está ativa enquanto está com um thread ocioso que não está em execução, ou seja, um thread ocioso que está aguardando a E/S de memória. Esse tipo de E/S domina a workload típica de banco de dados. 

É provável que os processos aguardem para serem programados em uma CPU quando as seguintes condições forem atendidas:
+ A métrica `CPUUtilization` do CloudWatch está próxima dos 100%.
+ A carga média é maior que o número de vCPUs, indicando uma carga pesada. Você pode encontrar a métrica `loadAverageMinute` na seção de métricas do sistema operacional do Performance Insights.

## Possíveis causas do maior número de esperas
<a name="wait-event.cpu.causes"></a>

Quando o evento de espera de CPU ocorre mais que o normal, possivelmente indicando um problema de performance, as causas típicas incluem:

**Topics**
+ [

### Possíveis causas de picos súbitos
](#wait-event.cpu.causes.spikes)
+ [

### Possíveis causas de alta frequência a longo prazo
](#wait-event.cpu.causes.long-term)
+ [

### Casos excepcionais
](#wait-event.cpu.causes.corner-cases)

### Possíveis causas de picos súbitos
<a name="wait-event.cpu.causes.spikes"></a>

As causas mais prováveis de picos súbitos são as seguintes:
+ Sua aplicação abriu muitas conexões simultâneas com o banco de dados. Esse cenário é conhecido como “tempestade de conexões”.
+ A workload da sua aplicação foi alterada de qualquer uma das seguintes maneiras:
  + Novas consultas
  + Um aumento no tamanho do conjunto de dados
  + Manutenção ou criação de índices
  + Novas funções
  + Novos operadores
  + Um aumento na execução de consultas paralelas
+ Seus planos de execução de consultas foram modificados. Em certos casos, uma alteração pode causar um aumento nos buffers. Por exemplo, a consulta agora está utilizando uma varredura sequencial quando utilizava anteriormente um índice. Nesse caso, ela precisa de mais CPU para atingir o mesmo objetivo.

### Possíveis causas de alta frequência a longo prazo
<a name="wait-event.cpu.causes.long-term"></a>

As causas mais prováveis de eventos que se repetem por um longo período são:
+ Muitos processos de backend estão em execução simultaneamente na CPU. Esses processos podem ser operadores paralelos.
+ Consultas estão sendo executadas com performance abaixo do ideal porque precisam de um grande número de buffers.

### Casos excepcionais
<a name="wait-event.cpu.causes.corner-cases"></a>

Se nenhuma das causas prováveis revelarem ser causas reais, as seguintes situações podem estar ocorrendo:
+ A CPU está alternando processos para dentro e para fora.
+ A CPU poderá estar gerenciando as entradas da tabela de páginas se o recurso de *páginas enormes* estiver desativado. Esse recurso de gerenciamento de memória é ativado por padrão para todas as classes de instância de banco de dados que não sejam classes de instância de banco de dados micro, pequenas e médias. Para obter mais informações, consulte [Páginas grandes para RDS para PostgreSQL](PostgreSQL.Concepts.General.FeatureSupport.HugePages.md). 

## Ações
<a name="wait-event.cpu.actions"></a>

Se o evento de espera `CPU` domina a atividade do banco de dados, isso não indica necessariamente um problema de performance. Responda a esse evento somente quando a performance diminuir.

**Topics**
+ [

### Investigar se o banco de dados está causando o aumento da CPU
](#wait-event.cpu.actions.db-CPU)
+ [

### Determinar se o número de conexões aumentou
](#wait-event.cpu.actions.connections)
+ [

### Responder a alterações de workload
](#wait-event.cpu.actions.workload)

### Investigar se o banco de dados está causando o aumento da CPU
<a name="wait-event.cpu.actions.db-CPU"></a>

Examine a métrica `os.cpuUtilization.nice.avg` no Performance Insights. Se esse valor for muito menor que o uso da CPU, processos que não são do banco de dados são os principais colaboradores para a CPU.

### Determinar se o número de conexões aumentou
<a name="wait-event.cpu.actions.connections"></a>

Examine a métrica `DatabaseConnections` no Amazon CloudWatch. Sua ação depende se o número aumentou ou diminuiu durante o período de maior número de eventos de espera de CPU.

#### As conexões aumentaram
<a name="wait-event.cpu.actions.connections.increased"></a>

Se o número de conexões aumentou, compare o número de processos de backend que consumem CPU com o número de vCPUs. Os cenários a seguir são possíveis:
+ O número de processos de backend que consomem CPU é menor que o número de vCPUs.

  Nesse caso, o número de conexões não é um problema. Porém, você ainda pode tentar reduzir a utilização da CPU.
+ O número de processos de backend que consomem CPU é maior que o número de vCPUs.

  Nesse caso, considere as opções a seguir:
  + Diminua o número de processos de backend conectados ao banco de dados. Por exemplo, implemente uma solução de agrupamento de conexões, como o RDS Proxy. Para saber mais, consulte [Amazon RDS Proxy](rds-proxy.md).
  + Atualize o tamanho da sua instância para obter um número maior de vCPUs.
  + Se aplicável, redirecione algumas workloads somente leitura para nós de leitor.

#### As conexões não aumentaram
<a name="wait-event.cpu.actions.connections.decreased"></a>

Examine as métricas `blks_hit` no Performance Insights. Procure uma correlação entre um aumento em `blks_hit` e o uso da CPU. Os cenários a seguir são possíveis:
+ O uso da CPU e `blks_hit` estão correlacionados.

  Nesse caso, encontre as principais instruções SQL vinculadas ao uso da CPU e procure modificações no plano. Você pode usar uma das seguintes técnicas:
  + Explicar os planos manualmente e compare-os com o plano de execução esperado.
  + Procurar um aumento nos acertos de bloco por segundo e nos acertos de blocos locais por segundo. Na seção **Top SQL** (SQL principal) do painel do Performance Insights, escolha **Preferences** (Preferências).
+ O uso da CPU e `blks_hit` não estão correlacionados.

  Nesse caso, determine se alguma das seguintes situações ocorre:
  + A aplicação está se conectando e se desconectando rapidamente ao/do banco de dados. 

    Diagnostique esse comportamento ativando `log_connections` e `log_disconnections` e analisando os logs do PostgreSQL. Considere utilizar o analisador de logs `pgbadger`. Para obter mais informações, consulte [https://github.com/darold/pgbadger](https://github.com/darold/pgbadger).
  + O sistema operacional está sobrecarregado.

    Nesse caso, o Performance Insights mostra que processos de backend estão consumindo CPU por mais tempo que o normal. Procure evidências nas métricas `os.cpuUtilization` do Performance Insights ou na métrica `CPUUtilization` do CloudWatch. Se o sistema operacional estiver sobrecarregado, consulte as métricas de monitoramento avançado para aprofundar o diagnóstico. Especificamente, observe a lista de processos e a porcentagem de CPU consumida por cada um.
  + As principais instruções SQL estão consumindo muita CPU.

    Examine instruções que estão vinculadas ao uso da CPU para verificar se elas podem utilizar menos CPU. Execute um comando `EXPLAIN` e concentre-se nos nós do plano que têm o maior impacto. Considere utilizar um visualizador de plano de execução do PostgreSQL. Para experimentar essa ferramenta, consulte [http://explain.dalibo.com/](http://explain.dalibo.com/).

### Responder a alterações de workload
<a name="wait-event.cpu.actions.workload"></a>

Se a sua workload mudou, procure os seguintes tipos de alterações:

Novas consultas  
Verifique se novas consultas são esperadas. Em caso positivo, verifique se os planos de execução dessas consultas e o número de execuções por segundo são os esperados.

Um aumento no tamanho do conjunto de dados  
Determine se o particionamento, caso ainda não esteja implementado, pode ajudar. Essa estratégia é capaz de reduzir o número de páginas que uma consulta precisa recuperar.

Manutenção ou criação de índices  
Verifique se a programação de manutenção é a esperada. Uma prática recomendada é agendar atividades de manutenção fora das atividades de pico.

Novas funções  
Confirme se essas funções são executadas conforme o esperado durante o teste. Especificamente, confira se o número de execuções por segundo é o esperado.

Novos operadores  
Verifique se eles funcionam conforme o esperado durante os testes.

Um aumento na execução de consultas paralelas  
Determine se alguma das situações a seguir ocorreu:  
+ As relações ou os índices envolvidos cresceram de repente a ponto de diferirem significativamente de `min_parallel_table_scan_size` ou `min_parallel_index_scan_size`.
+ Alterações recentes foram feitas em `parallel_setup_cost` ou `parallel_tuple_cost`.
+ Alterações recentes foram feitas em `max_parallel_workers` ou `max_parallel_workers_per_gather`.

# IO:BufFileRead and IO:BufFileWrite
<a name="wait-event.iobuffile"></a>

Os eventos `IO:BufFileRead` e `IO:BufFileWrite` ocorrem quando o RDS para PostgreSQL cria arquivos temporários. Quando as operações requerem mais memória do que os parâmetros de memória de trabalho definidos atualmente, elas gravam dados temporários no armazenamento persistente. Essa operação é chamada às vezes de *derramamento no disco*. Para obter mais informações sobre os arquivos temporários e o uso, consulte [Gerenciar arquivos temporários com o PostgreSQL](PostgreSQL.ManagingTempFiles.md).

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.iobuffile.context.supported)
+ [

## Contexto
](#wait-event.iobuffile.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.iobuffile.causes)
+ [

## Ações
](#wait-event.iobuffile.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.iobuffile.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.iobuffile.context"></a>

`IO:BufFileRead` e `IO:BufFileWrite` estão relacionados à área de memória de trabalho e a área de memória de trabalho de manutenção. Para obter mais informações sobre essas áreas de memória local, consulte [Resource Consumption](https://www.postgresql.org/docs/current/runtime-config-resource.html) (Consumo de recursos) na documentação do PostgreSQL.

O valor padrão para `work_mem` é 4 MB. Se uma sessão executar operações em paralelo, cada operador que lidar com o paralelismo usará 4 MB de memória. Por essa razão, defina `work_mem` com cautela. Se você aumentar demais esse valor, um banco de dados que execute muitas sessões poderá consumir muita memória. Se você definir um valor muito baixo, o RDS para PostgreSQL criará arquivos temporários no armazenamento local. A E/S de disco desses arquivos temporários pode reduzir a performance.

Se você observar a seguinte sequência de eventos, é possível que seu banco de dados esteja gerando arquivos temporários:

1. Redução súbita e acentuada na disponibilidade

1. Recuperação rápida para o espaço livre

Você também pode observar um padrão de “motosserra”. Esse padrão pode indicar que o banco de dados está criando arquivos pequenos constantemente.

## Possíveis causas do maior número de esperas
<a name="wait-event.iobuffile.causes"></a>

Em geral, esses eventos de espera são causados por operações que consomem mais memória do que é alocado pelos parâmetros `work_mem` ou `maintenance_work_mem`. Para compensar isso, as operações gravam em arquivos temporários. Causas comuns dos eventos `IO:BufFileRead` e `IO:BufFileWrite` incluem:

**Consultas que necessitam de mais memória do que existe na área de memória de trabalho**  
Consultas com as seguintes características utilizam a área de memória de trabalho:  
+ Junções de hash
+ `ORDER BY`Cláusula 
+ `GROUP BY`Cláusula 
+ `DISTINCT`
+ Funções de janela
+ `CREATE TABLE AS SELECT`
+ Atualização de visualizações materializadas

**Instruções que necessitam de mais memória do que existe na área de memória do trabalho de manutenção**  
As seguintes instruções usam a área de memória do trabalho de manutenção:  
+ `CREATE INDEX`
+ `CLUSTER`

## Ações
<a name="wait-event.iobuffile.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera.

**Topics**
+ [

### Identificar o problema
](#wait-event.iobuffile.actions.problem)
+ [

### Examinar suas consultas de junção
](#wait-event.iobuffile.actions.joins)
+ [

### Examinar suas consultas ORDER BY e GROUP BY
](#wait-event.iobuffile.actions.order-by)
+ [

### Evite utilizar a operação DISTINCT
](#wait-event.iobuffile.actions.distinct)
+ [

### Considere utilizar funções de janela em vez de funções GROUP BY
](#wait-event.iobuffile.actions.window)
+ [

### Investigar visualizações materializadas e instruções CTAS
](#wait-event.iobuffile.actions.mv-refresh)
+ [

### Utilizar pg\$1repack ao recriar índices
](#wait-event.iobuffile.actions.pg_repack)
+ [

### Aumentar maintenance\$1work\$1mem ao agrupar tabelas
](#wait-event.iobuffile.actions.cluster)
+ [

### Ajustar a memória para evitar IO:BufFileRead e IO:BufFileWrite
](#wait-event.iobuffile.actions.tuning-memory)

### Identificar o problema
<a name="wait-event.iobuffile.actions.problem"></a>

Você pode visualizar o uso de arquivos temporários diretamente no Insights de Performance. Para obter mais informações, consulte [Visualizar o uso de arquivos temporários com o Insights de Performance](PostgreSQL.ManagingTempFiles.Example.md). Quando o Insights de Performance está desabilitado, é possível observar um aumento nas operações `IO:BufFileRead` e `IO:BufFileWrite`.

Para identificar a origem do problema, você pode definir o parâmetro `log_temp_files` para registrar todas as consultas que geram mais do que o limite especificado de KB de arquivos temporários. Por padrão,`log_temp_files` está definido como `-1`, o que desativa esse recurso de registro em log. Se você definir esse parâmetro como `0`, o RDS para PostgreSQL registrará todos os arquivos temporários. Se você defini-lo como `1024`, o RDS para PostgreSQL registrará todas as consultas que geram arquivos temporários maiores que 1 MB. Para obter mais informações sobre `log_temp_files`, consulte o tópico sobre [Relatórios de erros e registro em log](https://www.postgresql.org/docs/current/runtime-config-logging.html), na documentação do PostgreSQL.

### Examinar suas consultas de junção
<a name="wait-event.iobuffile.actions.joins"></a>

É provável que sua consulta use junções. Por exemplo, a consulta a seguir une quatro tabelas.

```
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;
```

Uma causa possível dos picos no uso temporário de arquivos é um problema na própria consulta. Por exemplo, uma cláusula quebrada talvez não esteja filtrando as junções corretamente. Considere a segunda junção interna no exemplo a seguir.

```
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;
```

A consulta anterior junta `customer.id` com `customer.id` por engano, gerando um produto cartesiano entre cada cliente e cada pedido. Esse tipo de junção acidental gera arquivos temporários grandes. Dependendo do tamanho das tabelas, uma consulta cartesiana pode até mesmo lotar o armazenamento. Sua aplicação pode ter junções cartesianas quando as seguintes condições são atendidas:
+ Você percebe reduções grandes e acentuadas na disponibilidade do armazenamento, seguidas de uma rápida recuperação.
+ Nenhum índice está sendo criado.
+ Nenhuma instrução `CREATE TABLE FROM SELECT` está sendo emitida.
+ Nenhuma visualização materializada está sendo atualizada.

Para verificar se as tabelas estão sendo unidas utilizando as chaves apropriadas, inspecione suas diretivas de mapeamento de consultas e objetos relacionais. Lembre-se de que certas consultas da sua aplicação não são chamadas o tempo todo e que algumas consultas são geradas dinamicamente.

### Examinar suas consultas ORDER BY e GROUP BY
<a name="wait-event.iobuffile.actions.order-by"></a>

Em alguns casos, uma cláusula `ORDER BY` pode resultar no excesso de arquivos temporários. Considere as seguintes diretrizes:
+ Inclua somente colunas em uma cláusula `ORDER BY` quando elas precisarem ser ordenadas. Essa orientação é especialmente importante para consultas que retornam milhares de linhas e especificam muitas colunas na cláusula `ORDER BY`.
+ Considere criar índices para acelerar cláusulas `ORDER BY` quando elas correspondem a colunas que tenham a mesma ordem crescente ou decrescente. Índices parciais são preferíveis, pois são menores. Índices menores são lidos e percorridos com mais rapidez.
+ Se você criar índices para colunas que podem aceitar valores nulos, considere se deseja que esses valores nulos sejam armazenados no final ou no início dos índices.

  Se possível, reduza o número de linhas que precisam ser ordenadas, filtrando o conjunto de resultados. Se você usar instruções de cláusula `WITH` ou subconsultas, lembre-se de que uma consulta interna gera um conjunto de resultados e o transmite à consulta externa. Quanto mais linhas uma consulta puder remover, menos ordenação ela precisará fazer.
+ Se não precisar obter o conjunto completo de resultados, utilize a cláusula `LIMIT`. Por exemplo, se quiser apenas as cinco principais linhas, uma consulta utilizando a cláusula `LIMIT` não continuará gerando resultados. Dessa forma, essa consulta requer menos memória e arquivos temporários.

Uma consulta que usa uma cláusula `GROUP BY` também pode exigir arquivos temporários. Consultas `GROUP BY` resumem valores utilizando funções como as seguintes:
+ `COUNT`
+ `AVG`
+ `MIN`
+ `MAX`
+ `SUM`
+ `STDDEV`

Para ajustar consultas `GROUP BY`, siga as recomendações para consultas `ORDER BY`.

### Evite utilizar a operação DISTINCT
<a name="wait-event.iobuffile.actions.distinct"></a>

Se possível, evite utilizar a operação `DISTINCT` para remover linhas duplicadas. Quanto mais linhas desnecessárias e duplicadas sua consulta retornar, mais cara a operação `DISTINCT` se tornará. Se possível, adicione filtros à cláusula `WHERE` mesmo que você utilize os mesmos filtros para tabelas diferentes. Filtrar a consulta e a junção corretamente melhora a performance e reduz o uso de recursos. Isso também evita relatórios e resultados incorretos.

Se precisar usar `DISTINCT` para várias linhas de uma mesma tabela, considere criar um índice composto. O agrupamento de várias colunas em um índice pode melhorar o tempo para avaliar linhas distintas. Além disso, se utilizar o RDS para PostgreSQL versão 10 ou superior, você poderá correlacionar estatísticas entre várias colunas utilizando o comando `CREATE STATISTICS`.

### Considere utilizar funções de janela em vez de funções GROUP BY
<a name="wait-event.iobuffile.actions.window"></a>

Usando `GROUP BY`, você altera o conjunto de resultados e, em seguida, recupera o resultado agregado. Usando funções de janela, você agrega dados sem modificar o conjunto de resultados. Uma função de janela usa a cláusula `OVER` para fazer cálculos entre os conjuntos definidos pela consulta, correlacionando uma linha com outra. Você pode utilizar todas as funções `GROUP BY` em funções de janela, mas também utilizar funções como as seguintes:
+ `RANK`
+ `ARRAY_AGG`
+ `ROW_NUMBER`
+ `LAG`
+ `LEAD`

Para minimizar o número de arquivos temporários gerados por uma função de janela, remova duplicatas do mesmo conjunto de resultados quando precisar de duas agregações distintas. Considere a seguinte consulta.

```
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;
```

Você pode reescrever essa consulta com a cláusula `WINDOW` da seguinte maneira.

```
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);
```

Por padrão, o planejador de execução do RDS para PostgreSQL consolida nós semelhantes para que ele não duplique operações. No entanto, utilizando uma declaração explícita para o bloco de janelas, é possível manter a consulta com mais facilidade. Também é possível melhorar a performance ao evitar a duplicação.

### Investigar visualizações materializadas e instruções CTAS
<a name="wait-event.iobuffile.actions.mv-refresh"></a>

Quando uma visualização materializada é atualizada, ela executa uma consulta. Essa consulta pode conter uma operação como `GROUP BY`, `ORDER BY` ou `DISTINCT`. Durante uma atualização, é possível observar um grande número de arquivos temporários e os eventos de espera `IO:BufFileWrite` e `IO:BufFileRead`. Da mesma forma, quando você cria uma tabela com base em uma instrução `SELECT`, a instrução `CREATE TABLE` executa uma consulta. Para reduzir os arquivos temporários necessários, otimize a consulta.

### Utilizar pg\$1repack ao recriar índices
<a name="wait-event.iobuffile.actions.pg_repack"></a>

Quando você cria um índice, o mecanismo ordena o conjunto de resultados. À medida que o tamanho das tabelas aumenta e à medida que os valores na coluna indexada se tornam mais diversificados, os arquivos temporários exigem mais espaço. Na maioria dos casos, não é possível impedir a criação de arquivos temporários para tabelas grandes sem modificar a área de memória do trabalho de manutenção. Para obter mais informações sobre `maintenance_work_mem`, consulte [https://www.postgresql.org/docs/current/runtime-config-resource.html](https://www.postgresql.org/docs/current/runtime-config-resource.html) na documentação do PostgreSQL. 

Uma possível solução alternativa ao recriar um índice grande é utilizar a extensão pg\$1repack. Para obter mais informações, consulte o tópico sobre como [Reorganizar tabelas em bancos de dados PostgreSQL com bloqueios mínimos](https://reorg.github.io/pg_repack/), na documentação de pg\$1repack. Para obter informações sobre como configurar a extensão em sua instância de banco de dados do RDS para PostgreSQL, consulte [Reduzir o inchaço em tabelas e índices com a extensão pg\$1repack](Appendix.PostgreSQL.CommonDBATasks.pg_repack.md). 

### Aumentar maintenance\$1work\$1mem ao agrupar tabelas
<a name="wait-event.iobuffile.actions.cluster"></a>

O comando `CLUSTER` agrupa a tabela especificada por *table\$1name* com base em um índice existente especificado por *index\$1name*. O RDS para PostgreSQL recria fisicamente a tabela para corresponder à ordem de um determinado índice.

Quando o armazenamento magnético era predominante, o agrupamento era comum, pois a taxa de transferência de armazenamento era limitada. Agora que o armazenamento baseado em SSD é comum, o agrupamento tornou-se menos popular. No entanto, se você agrupar tabelas, ainda poderá aumentar a performance ligeiramente, dependendo do tamanho da tabela, do índice, da consulta e assim por diante. 

Se você executar o comando `CLUSTER` e observar os eventos de espera `IO:BufFileWrite` e `IO:BufFileRead`, ajuste `maintenance_work_mem`. Aumente o tamanho da memória para uma quantidade relativamente grande. Um valor alto significa que o mecanismo pode utilizar mais memória para a operação de agrupamento.

### Ajustar a memória para evitar IO:BufFileRead e IO:BufFileWrite
<a name="wait-event.iobuffile.actions.tuning-memory"></a>

Em algumas situações, você precisa ajustar a memória. Seu objetivo é equilibrar a memória nas seguintes áreas de consumo usando os parâmetros apropriados, da forma a seguir.
+ O valor `work_mem` 
+ A memória restante após descontar o valor `shared_buffers`
+ As conexões máximas abertas e em uso, o que é limitado por `max_connections`

Para obter mais informações sobre ajuste da memória, consulte [Resource Consumption](https://www.postgresql.org/docs/current/runtime-config-resource.html) (Consumo de recursos) na documentação do PostgreSQL. 

#### Aumentar o tamanho da área de memória de trabalho
<a name="wait-event.iobuffile.actions.tuning-memory.work-mem"></a>

Em algumas situações, a única opção é aumentar a memória utilizada pela sessão. Se as consultas estiverem gravadas corretamente e utilizando as chaves corretas para junções, considere aumentar o valor de `work_mem`. 

Para descobrir quantos arquivos temporários são gerados por uma consulta, defina `log_temp_files` como `0`. Se você aumentar o valor de `work_mem` para o valor máximo identificado nos logs, impedirá que a consulta gere arquivos temporários. No entanto, `work_mem` define o máximo por nó de plano para cada conexão ou operador paralelo. Se o banco de dados tiver 5.000 conexões e cada uma utilizar 256 MiB de memória, o mecanismo precisará de 1,2 TiB de RAM. Portanto, sua instância pode ficar sem memória.

#### Reservar memória suficiente para o grupo de buffer compartilhado
<a name="wait-event.iobuffile.actions.tuning-memory.shared-pool"></a>

Seu banco de dados usa áreas de memória, como o grupo de buffer compartilhado, e não apenas a área de memória de trabalho. Considere os requisitos dessas áreas de memória adicionais antes de aumentar `work_mem`.

Por exemplo, suponha que sua classe de instância do RDS para PostgreSQL seja db.r5.2xlarge. Essa classe tem 64 GiB de memória. Por padrão, 25% da memória são reservados para o grupo de buffer compartilhado. Depois de subtrair a quantidade alocada à área de memória compartilhada, permanecem 16.384 MB. Não aloque a memória restante exclusivamente à área de memória de trabalho, pois o sistema operacional e o mecanismo também precisam de memória.

A memória que é possível alocar a `work_mem` depende da classe da instância. Se você utilizar uma classe de instância maior, mais memória estará disponível. No entanto, no exemplo anterior, não é possível utilizar mais de 16 GiB. Caso contrário, sua instância estará indisponível quando ficar sem memória. Para recuperar a instância e retirá-la do estado indisponível, os serviços de automação do RDS para PostgreSQL são reiniciados automaticamente.

#### Gerenciar o número de conexões
<a name="wait-event.iobuffile.actions.tuning-memory.connections"></a>

Imagine que a sua instância de banco de dados tenha 5.000 conexões simultâneas. Cada conexão usa pelo menos 4 MiB de `work_mem`. O alto consumo de memória das conexões provavelmente diminuirá a performance. Em resposta, existem as seguintes opções:
+ Faça upgrade para uma classe de instância maior.
+ Diminua o número de conexões de banco de dados simultâneas utilizando um proxy de conexão ou pooler.

Para proxies, considere o Amazon RDS Proxy, o pgBouncer ou um pooler de conexão baseado na sua aplicação. Essa solução alivia a carga da CPU. Ela também reduz o risco quando todas as conexões exigem a área de memória de trabalho. Quando há menos conexões de banco de dados, é possível aumentar o valor de `work_mem`. Dessa forma, você reduz a ocorrência dos eventos de espera `IO:BufFileRead` e `IO:BufFileWrite`. Além disso, as consultas que aguardam a área de memória de trabalho são aceleradas significativamente.

# IO:DataFileRead
<a name="wait-event.iodatafileread"></a>

O evento `IO:DataFileRead` ocorre quando uma conexão aguarda em um processo de backend para ler uma página necessária do armazenamento porque essa página não está disponível na memória compartilhada.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.iodatafileread.context.supported)
+ [

## Contexto
](#wait-event.iodatafileread.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.iodatafileread.causes)
+ [

## Ações
](#wait-event.iodatafileread.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.iodatafileread.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.iodatafileread.context"></a>

Todas as consultas e operações de manipulação de dados (DML) acessam páginas no grupo de buffer. Instruções que podem induzir leituras incluem `SELECT`, `UPDATE` e `DELETE`. Por exemplo, um `UPDATE` pode ler páginas de tabelas ou índices. Se a página que está sendo solicitada ou atualizada não estiver no grupo de buffer compartilhado, essa leitura poderá gerar o evento `IO:DataFileRead`.

Como o grupo de buffer compartilhado é finito, ele pode ficar lotado. Nesse caso, solicitações de páginas que não estão na memória forçam o banco de dados a ler blocos do disco. Se o evento `IO:DataFileRead` ocorre com frequência, o grupo de buffer compartilhado pode ser pequeno demais para acomodar sua workload. Esse problema é grave para consultas `SELECT` que fazem a leitura de um grande número de linhas que não cabem no grupo de buffer. Para obter mais informações sobre o grupo de buffer, consulte [Resource Consumption](https://www.postgresql.org/docs/current/runtime-config-resource.html) (Consumo de recursos) na documentação do PostgreSQL.

## Possíveis causas do maior número de esperas
<a name="wait-event.iodatafileread.causes"></a>

As causas comuns do evento `IO:DataFileRead` incluem:

**Picos de conexão**  
Você pode encontrar várias conexões gerando o mesmo número de eventos de espera IO:DatafileRead. Nesse caso, pode ocorrer um pico (aumento súbito e grande) em eventos `IO:DataFileRead`. 

**Instruções SELECT e DML realizando varreduras sequenciais**  
Sua aplicação pode estar executando uma nova operação. Ou uma operação existente pode mudar por conta de um novo plano de execução. Nesses casos, procure tabelas (particularmente grandes) que tenham um valor de `seq_scan` maior. Encontre-as consultando `pg_stat_user_tables`. Para rastrear consultas que estão gerando mais operações de leitura, utilize a extensão `pg_stat_statements`.

**CTAS e CREATE INDEX para conjuntos de dados grandes**  
Um *CTAS* é uma instrução `CREATE TABLE AS SELECT`. Se você executar um CTAS utilizando um conjunto de dados grande como fonte ou criar um índice em uma tabela grande, o evento `IO:DataFileRead` poderá ocorrer. Quando você cria um índice, talvez o banco de dados precise ler o objeto inteiro utilizando uma varredura sequencial. Um CTAS gera leituras de `IO:DataFile` quando as páginas não estão na memória.

**Vários operadores de vacuum em execução ao mesmo tempo**  
Operadores de vacuum podem ser acionados manual ou automaticamente. Convém adotar uma estratégia de vacuum agressiva. No entanto, quando uma tabela possui muitas linhas atualizadas ou excluídas, as esperas de `IO:DataFileRead` aumentam. Depois que o espaço é recuperado, o tempo de vacuum gasto em `IO:DataFileRead` diminui.

**Ingestão de grandes quantidades de dados**  
Quando a aplicação ingere grandes quantidades de dados, operações `ANALYZE` podem ocorrer com mais frequência. O processo `ANALYZE` pode ser acionado por um launcher de autovacuum ou chamado manualmente.  
A operação `ANALYZE` lê um subconjunto da tabela. O número de páginas que devem ser varridas é calculado multiplicando-se 30 pelo valor de `default_statistics_target`. Para obter mais informações, consulte a [Documentação do PostgreSQL](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET). O parâmetro `default_statistics_target` aceita valores entre 1 e 10.000, em que o padrão é 100.

**Inanição de recursos**  
Se a largura de banda ou a CPU da rede da instância forem consumidas, o evento `IO:DataFileRead` poderá ocorrer com mais frequência.

## Ações
<a name="wait-event.iodatafileread.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera.

**Topics**
+ [

### Verificar filtros de predicados em busca de consultas que geram esperas
](#wait-event.iodatafileread.actions.filters)
+ [

### Minimizar o efeito de operações de manutenção
](#wait-event.iodatafileread.actions.maintenance)
+ [

### Responder a um alto número de conexões
](#wait-event.iodatafileread.actions.connections)

### Verificar filtros de predicados em busca de consultas que geram esperas
<a name="wait-event.iodatafileread.actions.filters"></a>

Suponha que você identifique consultas específicas que estão gerando eventos de espera `IO:DataFileRead`. É possível identificá-los utilizando as seguintes técnicas:
+ Insights de Performance
+ Visualizações de catálogo, como a fornecida pela extensão `pg_stat_statements`
+ A visualização de catálogo `pg_stat_all_tables`, se ela mostrar periodicamente um número mais alto de leituras físicas
+ A visualização `pg_statio_all_tables`, se ela mostrar que os contadores de `_read` estão aumentando

Convém determinar quais filtros são utilizados no predicado (cláusula `WHERE`) dessas consultas. Siga estas diretrizes:
+ Execute o comando `EXPLAIN`. Na saída, identifique quais tipos de varreduras são utilizados. Uma varredura sequencial não indica necessariamente um problema. Consultas que utilizam varreduras sequenciais naturalmente produzem mais eventos `IO:DataFileRead` quando comparados a consultas que utilizam filtros.

  Descubra se a coluna listada na cláusula `WHERE` é indexada. Caso contrário, considere criar um índice para essa coluna. Essa abordagem evita varreduras sequenciais e reduz eventos `IO:DataFileRead`. Se uma consulta tiver filtros restritivos e ainda produzir varreduras sequenciais, avalie se os índices adequados estão sendo utilizados.
+ Descubra se a consulta está acessando uma tabela muito grande. Em alguns casos, o particionamento de uma tabela pode melhorar a performance, permitindo que a consulta leia apenas as partições necessárias.
+ Observe a cardinalidade (número total de linhas) das suas operações de junção. Observe o quão restritivos são os valores que você está transmitindo nos filtros para a sua cláusula `WHERE`. Se possível, ajuste sua consulta para reduzir o número de linhas que são transmitidas em cada etapa do plano.

### Minimizar o efeito de operações de manutenção
<a name="wait-event.iodatafileread.actions.maintenance"></a>

Operações de manutenção, como `VACUUM` e `ANALYZE`, são importantes. Recomendamos que você não as desative ao encontrar eventos de espera `IO:DataFileRead` relacionados a essas operações de manutenção. As abordagens a seguir podem minimizar o efeito dessas operações:
+ Execute operações de manutenção manualmente fora do horário de pico. Essa técnica impede que o banco de dados atinja o limite para operações automáticas.
+ Considere particionar tabelas muito grandes. Essa técnica reduz a sobrecarga das operações de manutenção. O banco de dados somente acessa as partições que exigem manutenção.
+ Ao ingerir grandes quantidades de dados, considere desativar o recurso de análise automática.

O recurso de autovacuum é acionado automaticamente para uma tabela quando a seguinte fórmula é verdadeira.

```
pg_stat_user_tables.n_dead_tup > (pg_class.reltuples x autovacuum_vacuum_scale_factor) + autovacuum_vacuum_threshold
```

A visualização `pg_stat_user_tables` e o catálogo `pg_class` têm várias linhas. Uma linha pode corresponder a uma linha na sua tabela. Essa fórmula pressupõe que os `reltuples` sejam para uma tabela específica. Os parâmetros `autovacuum_vacuum_scale_factor` (0,20 por padrão) e `autovacuum_vacuum_threshold` (50 tuplas por padrão) geralmente são definidos globalmente para toda a instância. Porém, é possível definir valores diferentes para uma tabela específica.

**Topics**
+ [

#### Localizar tabelas que consomem espaço desnecessariamente
](#wait-event.iodatafileread.actions.maintenance.tables)
+ [

#### Localizar índices que consomem espaço desnecessariamente
](#wait-event.iodatafileread.actions.maintenance.indexes)
+ [

#### Localizar tabelas elegíveis qualificadas para receber autovacuum
](#wait-event.iodatafileread.actions.maintenance.autovacuumed)

#### Localizar tabelas que consomem espaço desnecessariamente
<a name="wait-event.iodatafileread.actions.maintenance.tables"></a>

Para encontrar tabelas que consomem espaço desnecessariamente, você pode usar funções da extensão `pgstattuple` do PostgreSQL. Essa extensão (módulo) está disponível por padrão em todas as instâncias de banco de dados do RDS para PostgreSQL e pode ser instanciada na instância com o comando a seguir.

```
CREATE EXTENSION pgstattuple;
```

Para obter mais informações sobre essa extensão, consulte [pgstattuple](https://www.postgresql.org/docs/current/pgstattuple.html) na documentação do PostgreSQL.

É possível verificar se há sobrecarga na tabela e no índice em sua aplicação. Para obter mais informações, consulte [Diagnosticar a sobrecarga na tabela e no índice](https://docs.aws.amazon.com//AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.diag-table-ind-bloat.html).

#### Localizar índices que consomem espaço desnecessariamente
<a name="wait-event.iodatafileread.actions.maintenance.indexes"></a>

Para encontrar índices inchados e estimar a quantidade de espaço consumida desnecessariamente nas tabelas para as quais você tem privilégios de leitura, é possível executar a consulta a seguir.

```
-- WARNING: rows with is_na = 't' are known to have bad statistics ("name" type is not supported).
-- This query is compatible with PostgreSQL 8.2 and later.

SELECT current_database(), nspname AS schemaname, tblname, idxname, bs*(relpages)::bigint AS real_size,
  bs*(relpages-est_pages)::bigint AS extra_size,
  100 * (relpages-est_pages)::float / relpages AS extra_ratio,
  fillfactor, bs*(relpages-est_pages_ff) AS bloat_size,
  100 * (relpages-est_pages_ff)::float / relpages AS bloat_ratio,
  is_na
  -- , 100-(sub.pst).avg_leaf_density, est_pages, index_tuple_hdr_bm, 
  -- maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, sub.reltuples, sub.relpages 
  -- (DEBUG INFO)
FROM (
  SELECT coalesce(1 +
       ceil(reltuples/floor((bs-pageopqdata-pagehdr)/(4+nulldatahdrwidth)::float)), 0 
       -- ItemIdData size + computed avg size of a tuple (nulldatahdrwidth)
    ) AS est_pages,
    coalesce(1 +
       ceil(reltuples/floor((bs-pageopqdata-pagehdr)*fillfactor/(100*(4+nulldatahdrwidth)::float))), 0
    ) AS est_pages_ff,
    bs, nspname, table_oid, tblname, idxname, relpages, fillfactor, is_na
    -- , stattuple.pgstatindex(quote_ident(nspname)||'.'||quote_ident(idxname)) AS pst, 
    -- index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, reltuples 
    -- (DEBUG INFO)
  FROM (
    SELECT maxalign, bs, nspname, tblname, idxname, reltuples, relpages, relam, table_oid, fillfactor,
      ( index_tuple_hdr_bm +
          maxalign - CASE -- Add padding to the index tuple header to align on MAXALIGN
            WHEN index_tuple_hdr_bm%maxalign = 0 THEN maxalign
            ELSE index_tuple_hdr_bm%maxalign
          END
        + nulldatawidth + maxalign - CASE -- Add padding to the data to align on MAXALIGN
            WHEN nulldatawidth = 0 THEN 0
            WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign
            ELSE nulldatawidth::integer%maxalign
          END
      )::numeric AS nulldatahdrwidth, pagehdr, pageopqdata, is_na
      -- , index_tuple_hdr_bm, nulldatawidth -- (DEBUG INFO)
    FROM (
      SELECT
        i.nspname, i.tblname, i.idxname, i.reltuples, i.relpages, i.relam, a.attrelid AS table_oid,
        current_setting('block_size')::numeric AS bs, fillfactor,
        CASE -- MAXALIGN: 4 on 32bits, 8 on 64bits (and mingw32 ?)
          WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8
          ELSE 4
        END AS maxalign,
        /* per page header, fixed size: 20 for 7.X, 24 for others */
        24 AS pagehdr,
        /* per page btree opaque data */
        16 AS pageopqdata,
        /* per tuple header: add IndexAttributeBitMapData if some cols are null-able */
        CASE WHEN max(coalesce(s.null_frac,0)) = 0
          THEN 2 -- IndexTupleData size
          ELSE 2 + (( 32 + 8 - 1 ) / 8) 
          -- IndexTupleData size + IndexAttributeBitMapData size ( max num filed per index + 8 - 1 /8)
        END AS index_tuple_hdr_bm,
        /* data len: we remove null values save space using it fractionnal part from stats */
        sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024)) AS nulldatawidth,
        max( CASE WHEN a.atttypid = 'pg_catalog.name'::regtype THEN 1 ELSE 0 END ) > 0 AS is_na
      FROM pg_attribute AS a
        JOIN (
          SELECT nspname, tbl.relname AS tblname, idx.relname AS idxname, 
            idx.reltuples, idx.relpages, idx.relam,
            indrelid, indexrelid, indkey::smallint[] AS attnum,
            coalesce(substring(
              array_to_string(idx.reloptions, ' ')
               from 'fillfactor=([0-9]+)')::smallint, 90) AS fillfactor
          FROM pg_index
            JOIN pg_class idx ON idx.oid=pg_index.indexrelid
            JOIN pg_class tbl ON tbl.oid=pg_index.indrelid
            JOIN pg_namespace ON pg_namespace.oid = idx.relnamespace
          WHERE pg_index.indisvalid AND tbl.relkind = 'r' AND idx.relpages > 0
        ) AS i ON a.attrelid = i.indexrelid
        JOIN pg_stats AS s ON s.schemaname = i.nspname
          AND ((s.tablename = i.tblname AND s.attname = pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE)) 
          -- stats from tbl
          OR  (s.tablename = i.idxname AND s.attname = a.attname))
          -- stats from functional cols
        JOIN pg_type AS t ON a.atttypid = t.oid
      WHERE a.attnum > 0
      GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9
    ) AS s1
  ) AS s2
    JOIN pg_am am ON s2.relam = am.oid WHERE am.amname = 'btree'
) AS sub
-- WHERE NOT is_na
ORDER BY 2,3,4;
```

#### Localizar tabelas elegíveis qualificadas para receber autovacuum
<a name="wait-event.iodatafileread.actions.maintenance.autovacuumed"></a>

Para localizar tabelas qualificadas para receber autovacuum, execute a seguinte consulta.

```
--This query shows tables that need vacuuming and are eligible candidates.
--The following query lists all tables that are due to be processed by autovacuum. 
-- During normal operation, this query should return very little.
WITH  vbt AS (SELECT setting AS autovacuum_vacuum_threshold 
              FROM pg_settings WHERE name = 'autovacuum_vacuum_threshold')
    , vsf AS (SELECT setting AS autovacuum_vacuum_scale_factor 
              FROM pg_settings WHERE name = 'autovacuum_vacuum_scale_factor')
    , fma AS (SELECT setting AS autovacuum_freeze_max_age 
              FROM pg_settings WHERE name = 'autovacuum_freeze_max_age')
    , sto AS (SELECT opt_oid, split_part(setting, '=', 1) as param, 
                split_part(setting, '=', 2) as value 
              FROM (SELECT oid opt_oid, unnest(reloptions) setting FROM pg_class) opt)
SELECT
    '"'||ns.nspname||'"."'||c.relname||'"' as relation
    , pg_size_pretty(pg_table_size(c.oid)) as table_size
    , age(relfrozenxid) as xid_age
    , coalesce(cfma.value::float, autovacuum_freeze_max_age::float) autovacuum_freeze_max_age
    , (coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + 
         coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples) 
         as autovacuum_vacuum_tuples
    , n_dead_tup as dead_tuples
FROM pg_class c 
JOIN pg_namespace ns ON ns.oid = c.relnamespace
JOIN pg_stat_all_tables stat ON stat.relid = c.oid
JOIN vbt on (1=1) 
JOIN vsf ON (1=1) 
JOIN fma on (1=1)
LEFT JOIN sto cvbt ON cvbt.param = 'autovacuum_vacuum_threshold' AND c.oid = cvbt.opt_oid
LEFT JOIN sto cvsf ON cvsf.param = 'autovacuum_vacuum_scale_factor' AND c.oid = cvsf.opt_oid
LEFT JOIN sto cfma ON cfma.param = 'autovacuum_freeze_max_age' AND c.oid = cfma.opt_oid
WHERE c.relkind = 'r' 
AND nspname <> 'pg_catalog'
AND (
    age(relfrozenxid) >= coalesce(cfma.value::float, autovacuum_freeze_max_age::float)
    or
    coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + 
      coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples <= n_dead_tup
    -- or 1 = 1
)
ORDER BY age(relfrozenxid) DESC;
```

### Responder a um alto número de conexões
<a name="wait-event.iodatafileread.actions.connections"></a>

Ao monitorar o Amazon CloudWatch, você pode descobrir que a métrica `DatabaseConnections` atinge picos. Esse aumento indica um número maior de conexões com o seu banco de dados. Recomendamos a seguinte abordagem:
+ Limite o número de conexões que a aplicação pode abrir com cada instância. Se a aplicação tiver um recurso de grupo de conexões incorporado, defina um número razoável de conexões. Baseie o número no que as vCPUs na instância podem paralelizar de maneira eficiente.

  Se a aplicação não utilizar um recurso de grupo de conexões, considere utilizar o Amazon RDS Proxy ou uma alternativa. Essa abordagem permite que a aplicação abra várias conexões com o balanceador de carga. O balanceador pode então abrir um número restrito de conexões com o banco de dados. À medida que menos conexões são executadas em paralelo, sua instância de banco de dados realiza menos alternâncias de contexto no kernel. As consultas devem progredir com mais rapidez, resultando em menos eventos de espera. Para obter mais informações, consulte [Amazon RDS Proxy](rds-proxy.md).
+ Sempre que possível, aproveite réplicas de leitura para o RDS para PostgreSQL. Quando sua aplicação executar uma operação somente leitura, envie essas solicitações às réplicas de leitura. Essa técnica reduz a pressão de E/S no nó primário (gravador).
+ Considere aumentar a escala vertical da sua instância de banco de dados. Uma classe de instância com maior capacidade fornece mais memória, o que dá ao RDS para PostgreSQL um grupo de buffer compartilhado maior para conter páginas. O tamanho maior também dá à instância de banco de dados mais vCPUs para lidar com conexões. Mais vCPUs são particularmente úteis quando as operações que estão gerando eventos de espera `IO:DataFileRead` são gravações.

# IO:WALWrite
<a name="wait-event.iowalwrite"></a>



**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.iowalwrite.context.supported)
+ [

## Contexto
](#wait-event.iowalwrite.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.iowalwrite.causes)
+ [

## Ações
](#wait-event.iowalwrite.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.iowalwrite.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL 10 e posteriores.

## Contexto
<a name="wait-event.iowalwrite.context"></a>

A atividade no banco de dados que está gerando dados de log de gravação antecipada preenche primeiro os buffers do WAL e depois grava no disco, de forma assíncrona. O evento de espera `IO:WALWrite` é gerado quando a sessão SQL aguarda a conclusão da gravação dos dados do WAL no disco para que ela possa liberar a chamada COMMIT da transação. 

## Possíveis causas do maior número de esperas
<a name="wait-event.iowalwrite.causes"></a>

Se esse evento de espera ocorrer com frequência, você deve revisar sua workload, o tipo de atualização que ela executa e sua frequência. Especificamente, procure os tipos de atividade a seguir.

**Atividade intensa de DML**  
A alteração de dados nas tabelas do banco de dados não acontece instantaneamente. Uma inserção em uma tabela pode precisar aguardar uma inserção ou uma atualização para a mesma tabela de outro cliente. As instruções da linguagem de manipulação de dados (DML) para alterar valores de dados (INSERT, UPDATE, DELETE, COMMIT, ROLLBACK TRANSACTION) podem ocasionar contenções que fazem com que o arquivo de registro de gravação antecipada aguarde a liberação dos buffers. Essa situação é capturada nas métricas a seguir do Insights de Performance do Amazon RDS, que indicam atividade intensa de DML.  
+  `tup_inserted`
+ `tup_updated`
+ `tup_deleted`
+ `xact_rollback`
+ `xact_commit`
Para ter mais informações sobre essas métricas, consulte [Contadores do Performance Insights para o Amazon RDS para PostgreSQL](USER_PerfInsights_Counters.md#USER_PerfInsights_Counters.PostgreSQL).

**Atividade frequente no ponto de verificação**  
Pontos de verificação frequentes contribuem para um maior número de arquivos WAL. No RDS para PostgreSQL, as gravações de página inteira estão sempre “ativadas”. As gravações de página inteira ajudam a proteger contra a perda de dados. No entanto, quando a verificação ocorre com muita frequência, o sistema pode sofrer problemas gerais de performance. Isso é especialmente verdadeiro em sistemas com intensa atividade de DML. Em alguns casos, você pode encontrar mensagens de erro em seu `postgresql.log` afirmando que “os pontos de verificação estão ocorrendo com muita frequência”.   
Recomendamos que, ao ajustar os pontos de verificação, você equilibre cuidadosamente a performance com o tempo esperado de recuperação no caso de um desligamento anormal. 

## Ações
<a name="wait-event.iowalwrite.actions"></a>

Recomendamos as ações a seguir para reduzir os números desse evento de espera.

**Topics**
+ [

### Reduza o número de confirmações
](#wait-event.iowalwrite.actions.problem)
+ [

### Monitorar os pontos de verificação
](#wait-event.iowalwrite.actions.monitor)
+ [

### Aumentar a escala de E/S verticalmente
](#wait-event.iowalwrite.actions.scale-io)
+ [

### Volume de log dedicado (DLV)
](#wait-event.iowalwrite.actions.dlv)

### Reduza o número de confirmações
<a name="wait-event.iowalwrite.actions.problem"></a>

Para reduzir o número de confirmações, você pode combinar instruções em blocos de transações. Utilize o Insights de Performance do Amazon RDS para examinar o tipo de consulta que está sendo executada. Você também pode transferir grandes operações de manutenção para o horário de pico. Por exemplo, crie índices ou use operações `pg_repack` fora do horário de produção.

### Monitorar os pontos de verificação
<a name="wait-event.iowalwrite.actions.monitor"></a>

Há dois parâmetros que você pode monitorar para ver com que frequência sua instância de banco de dados do RDS para PostgreSQL está gravando no arquivo WAL para pontos de verificação. 
+ `log_checkpoints`: por padrão, esse parâmetro está ativado. Isso faz com que uma mensagem seja enviada ao log do PostgreSQL para cada ponto de verificação. Essas mensagens de log incluem o número de buffers gravados, o tempo gasto para gravá-los e o número de arquivos WAL adicionados, removidos ou reciclados para determinado ponto de verificação. 

  Para obter mais informações sobre esse parâmetro, consulte [Error Reporting and Logging](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-CHECKPOINTS) (Relatórios de erros e registro em log) na documentação do PostgreSQL. 
+ `checkpoint_warning`: esse parâmetro define um valor limite (em segundos) para a frequência do ponto de verificação acima da qual um aviso é gerado. Por padrão, esse parâmetro não é definido no RDS para PostgreSQL. Você pode definir o valor desse parâmetro para receber um aviso quando as alterações do banco de dados em sua instância de banco de dados do RDS para PostgreSQL forem gravadas a uma taxa para a qual os arquivos WAL não estão dimensionados para serem manipulados. Por exemplo, digamos que você definiu esse parâmetro como 30. Se sua instância do RDS para PostgreSQL precisar gravar alterações com maior frequência do que a cada 30 segundos, o aviso de que “pontos de verificação estão ocorrendo com muita frequência” será enviado ao log do PostgreSQL. Isso pode indicar que seu valor `max_wal_size` deve ser aumentado. 

  Para obter mais informações, consulte [Write Ahead Log](https://www.postgresql.org/docs/current/runtime-config-wal.html#RUNTIME-CONFIG-WAL-CHECKPOINTS) (Log de gravação antecipada) na documentação do PostgreSQL. 

### Aumentar a escala de E/S verticalmente
<a name="wait-event.iowalwrite.actions.scale-io"></a>

Esse tipo de evento de espera de entrada/saída (IO) pode ser corrigido escalando as operações de entrada e saída por segundo (IOPs) para fornecer uma E/S mais rápida. Escalar a E/S é preferível a escalar a CPU, porque escalar a CPU pode ocasionar ainda mais contenção de E/S, pois a CPU aumentada pode lidar com mais trabalho e, assim, piorar ainda mais o gargalo de E/S. Em geral, recomendamos que você considere ajustar sua workload antes de realizar operações de escalabilidade.

### Volume de log dedicado (DLV)
<a name="wait-event.iowalwrite.actions.dlv"></a>

Use um volume de log dedicado (DLV) para uma instância de banco de dados que usa o armazenamento de IOPS provisionadas (PIOPS) utilizando o console do Amazon RDS, AWS CLI a ou a API do Amazon RDS. Um DLV move os logs de transações do banco de dados do PostgreSQL para um volume de armazenamento separado do volume que contém as tabelas do banco de dados. Para ter mais informações, consulte [Volume de log dedicado (DLV)](CHAP_Storage.md#CHAP_Storage.dlv).

# IPC: eventos de espera paralelos
<a name="rpg-ipc-parallel"></a>

Os seguintes `IPC:parallel wait events` indicam que uma sessão está aguardando a comunicação entre processos relacionada às operações de execução paralela de consultas.
+ `IPC:BgWorkerStartup`: um processo está aguardando um processo de operador concluir sua sequência de inicialização. Isso acontece ao inicializar operadores para execução paralela de consultas.
+ `IPC:BgWorkerShutdown`: um processo está aguardando um processo de operador concluir sua sequência de shutdown. Isso ocorre durante a fase de limpeza da execução paralela da consulta.
+ `IPC:ExecuteGather`: um processo está aguardando para receber dados de processos de operador paralelos durante a execução da consulta. Isso ocorre quando o processo líder precisa coletar resultados de seus operadores.
+ `IPC:ParallelFinish`: um processo está aguardando operadores paralelos terminarem sua execução e relatarem seus resultados finais. Isso acontece durante a fase de conclusão da execução paralela da consulta.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#rpg-ipc-parallel-context-supported)
+ [

## Contexto
](#rpg-ipc-parallel-context)
+ [

## Possíveis causas do maior número de esperas
](#rpg-ipc-parallel-causes)
+ [

## Ações
](#rpg-ipc-parallel-actions)

## Versões compatíveis do mecanismo
<a name="rpg-ipc-parallel-context-supported"></a>

Essas informações de eventos de espera têm suporte para todas as versões do Aurora PostgreSQL.

## Contexto
<a name="rpg-ipc-parallel-context"></a>

A execução paralela de consultas no PostgreSQL envolve vários processos trabalhando juntos para processar uma única consulta. Quando uma consulta é determinada como adequada para paralelização, um processo líder se coordena com um ou mais processos de operador paralelos com base na configuração de parâmetros `max_parallel_workers_per_gather`. O processo líder divide o trabalho entre os operadores, cada um processa sua parte dos dados de forma independente e os resultados são reunidos de volta ao processo líder.

**nota**  
Cada operador paralelo opera como um processo separado com requisitos de recursos semelhantes a uma sessão completa de usuário. Isso significa que uma consulta paralela com 4 operadores pode consumir até 5 vezes mais recursos (CPU, memória, largura de banda de E/S) em comparação com uma consulta não paralela, pois tanto o processo líder quanto cada processo de operador mantêm suas próprias alocações de recursos. Por exemplo, configurações como `work_mem` são aplicadas individualmente a cada operador, potencialmente multiplicando o uso total de memória em todos os processos.

A arquitetura de consulta paralela consiste em três componentes principais:
+ Processo líder: o processo principal que inicia a operação paralela, divide a workload e coordena com os processos de operador.
+ Processos de operador: processos em segundo plano que executam partes da consulta em paralelo.
+ Fusão Gather/Gather: operações que combinam resultados de vários processos de operador de volta ao líder

Durante a execução paralela, os processos precisam se comunicar entre si por meio de mecanismos de comunicação entre processos (IPC). Esses eventos de espera do IPC ocorrem durante diferentes fases:
+ Inicialização do operador: quando operadores paralelos estão sendo inicializados
+ Troca de dados: quando os operadores estão processando dados e enviando resultados para o líder
+ Encerramento do operador: quando a execução paralela é concluída e os operadores estão sendo encerrados
+ Pontos de sincronização: quando os processos precisam se coordenar ou esperar que outros processos concluam suas tarefas

Compreender esses eventos de espera é crucial para diagnosticar problemas de desempenho relacionados à execução paralela de consultas, especialmente em ambientes de alta concorrência, nos quais várias consultas paralelas podem ser executadas simultaneamente.

## Possíveis causas do maior número de esperas
<a name="rpg-ipc-parallel-causes"></a>

Vários fatores podem contribuir para um aumento nos eventos de espera do IPC relacionados ao paralelismo:

**Alta concorrência de consultas paralelas**  
Quando muitas consultas paralelas são executadas simultaneamente, isso pode levar à contenção de recursos e ao aumento do tempo de espera para operações de IPC. Isso é particularmente comum em sistemas com altos volumes de transações ou workloads analíticas.

**Planos de consulta paralela subótimos**  
Se o planejador de consultas escolher planos paralelos ineficientes, isso poderá resultar em paralelização desnecessária ou má distribuição do trabalho entre os operadores. Isso pode levar ao aumento das esperas de IPC, especialmente para eventos `IPC:ExecuteGather` e `IPC:ParallelFinish`. Esses problemas de planejamento geralmente resultam de estatísticas desatualizadas e do inchaço da tabela/índice.

**Inicialização e encerramento frequentes de operadores paralelos**  
Consultas de curta duração que frequentemente iniciam e encerram operadores paralelos podem causar um aumento nos eventos `IPC:BgWorkerStartup` e `IPC:BgWorkerShutdown`. Isso geralmente é visto em workloads OLTP com muitas consultas pequenas e paralelizáveis.

**Restrições de recursos**  
A capacidade limitada de CPU, memória ou E/S pode causar gargalos na execução paralela, levando ao aumento do tempo de espera em todos os eventos de IPC. Por exemplo, se a CPU estiver saturada, os processos de operador podem levar mais tempo para iniciar ou processar sua parte do trabalho.

**Estruturas complexas de consulta**  
Consultas com vários níveis de paralelismo (por exemplo, junções paralelas seguidas por agregações paralelas) podem levar a padrões de IPC mais complexos e a tempos de espera potencialmente maiores, especialmente para eventos `IPC:ExecuteGather`.

**Conjuntos de resultados grandes**  
Consultas que produzem grandes conjuntos de resultados podem causar maiores tempos de espera `IPC:ExecuteGather`, pois o processo líder passa mais tempo coletando e processando resultados dos processos de operador.

Entender esses fatores pode ajudar a diagnosticar e resolver problemas de desempenho relacionados à execução paralela de consultas no Aurora PostgreSQL.

## Ações
<a name="rpg-ipc-parallel-actions"></a>

Quando você vê esperas relacionadas à consulta paralela, isso normalmente significa que um processo de backend está coordenando ou aguardando processos de operador paralelos. Essas esperas são comuns durante a execução de planos paralelos. Você pode investigar e mitigar o impacto dessas esperas monitorando o uso de operadores paralelos, revisando as configurações de parâmetros e ajustando a execução da consulta e a alocação de recursos.

**Topics**
+ [

### Analisar planos de consulta para paralelismo ineficiente
](#rpg-ipc-parallel-analyze-plans)
+ [

### Monitorar o uso de consultas paralelas
](#rpg-ipc-parallel-monitor)
+ [

### Revisar e ajustar as configurações de consulta paralela
](#rpg-ipc-parallel-adjust-settings)
+ [

### Otimizar a alocação de recursos
](#rpg-ipc-parallel-optimize-resources)
+ [

### Investigar o gerenciamento de conexão
](#rpg-ipc-parallel-connection-management)
+ [

### Revisar e otimizar as operações de manutenção
](#rpg-ipc-parallel-maintenance)

### Analisar planos de consulta para paralelismo ineficiente
<a name="rpg-ipc-parallel-analyze-plans"></a>

A execução paralela de consultas pode frequentemente levar à instabilidade do sistema, picos de CPU e variações imprevisíveis no desempenho da consulta. É crucial analisar minuciosamente se o paralelismo realmente melhora sua workload específica. Use EXPLAIN ANALYZE para revisar os planos de execução de consultas paralelas.

Desative temporariamente o paralelismo no nível da sessão para comparar a eficiência do plano:

```
SET max_parallel_workers_per_gather = 0;
EXPLAIN ANALYZE <your_query>;
```

Reative o paralelismo e compare:

```
RESET max_parallel_workers_per_gather;
EXPLAIN ANALYZE <your_query>;
```

Se a desativação do paralelismo produzir resultados melhores ou mais consistentes, desative-o para consultas específicas no nível da sessão usando os comandos SET. Para um impacto mais amplo, você pode querer desabilitar o paralelismo no nível da instância ajustando os parâmetros relevantes em seu grupo de parâmetros do banco de dados. Para obter mais informações, consulte [Modificar parâmetros em um grupo de parâmetros de banco de dados no Amazon RDS](USER_WorkingWithParamGroups.Modifying.md).

### Monitorar o uso de consultas paralelas
<a name="rpg-ipc-parallel-monitor"></a>

Use as consultas a seguir para obter visibilidade da atividade e da capacidade de consultas paralelas:

Verifique os processos de operador paralelos ativos:

```
SELECT
    COUNT(*)
FROM
    pg_stat_activity
WHERE
    backend_type = 'parallel worker';
```

Esta consulta mostra o número de processos de operador paralelos ativos. Um valor alto pode indicar que seu `max\$1parallel\$1workers` está configurado com um valor alto e você pode querer reduzi-lo.

Verifique as consultas paralelas simultâneas:

```
SELECT
    COUNT(DISTINCT leader_pid)
FROM
    pg_stat_activity
WHERE
    leader_pid IS NOT NULL;
```

Essa consulta retorna o número de processos líderes distintos que iniciaram consultas paralelas. Um número alto aqui indica que várias sessões estão executando consultas paralelas simultaneamente, o que pode aumentar a demanda de CPU e memória.

### Revisar e ajustar as configurações de consulta paralela
<a name="rpg-ipc-parallel-adjust-settings"></a>

Analise os seguintes parâmetros para garantir que estejam alinhados à sua workload:
+ `max_parallel_workers`: número total de workers paralelos em todas as sessões.
+ `max_parallel_workers_per_gather`: máximo de workers por consulta.

Para workloads OLAP, aumentar esses valores pode melhorar o desempenho. Para workloads OLTP, valores mais baixos geralmente são preferidos.

```
SHOW max_parallel_workers;
SHOW max_parallel_workers_per_gather;
```

### Otimizar a alocação de recursos
<a name="rpg-ipc-parallel-optimize-resources"></a>

Monitore a utilização da CPU e ajuste o número de vCPUs se for consistentemente alto e se seu aplicativo se beneficiar de consultas paralelas. Verifique se há memória adequada disponível para operações paralelas.
+ Use as métricas do Performance Insights para determinar se o sistema está limitado pela CPU.
+ Cada operador paralelo usa o seu próprio `work_mem`. Verifique se o uso total da memória está dentro dos limites da instância.

As consultas paralelas podem consumir substancialmente mais recursos do que as consultas não paralelas, porque cada processo de operador é completamente separado que tem aproximadamente o mesmo impacto no sistema que uma sessão de usuário adicional. Isso deve ser levado em consideração ao escolher um valor para essa configuração, bem como ao definir outras configurações que controlam a utilização de recursos, como `work_mem`. Para obter mais informações, consulte a [Documentação do PostgreSQL](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-WORK-MEM). Limites de recursos, como `work_mem`, são aplicados individualmente a cada operador, o que significa que a utilização total pode ser muito maior em todos os processos do que normalmente seria em qualquer processo único.

Aumente as vCPUs ou ajuste os parâmetros de memória se sua workload estiver altamente paralelizada.

### Investigar o gerenciamento de conexão
<a name="rpg-ipc-parallel-connection-management"></a>

Se estiver experimentando esgotamento de conexões, revise as estratégias de pool de conexões do aplicativo. Implemente o pool de conexões no nível do aplicativo, se ainda não estiver em uso.

### Revisar e otimizar as operações de manutenção
<a name="rpg-ipc-parallel-maintenance"></a>

Coordene a criação de índices e outras tarefas de manutenção para evitar a contenção de recursos. Agende essas operações fora do horário de pico. Evite agendar manutenções pesadas (por exemplo, construções paralelas de índices) durante períodos de alta carga de consultas do usuário. Essas operações podem consumir workers paralelos e impactar o desempenho de consultas regulares.

# IPC:ProcArrayGroupUpdate
<a name="apg-rpg-ipcprocarraygroup"></a>

O evento `IPC:ProcArrayGroupUpdate` ocorre quando uma sessão está aguardando o líder do grupo atualizar o status da transação ao final dessa operação. Embora o PostgreSQL geralmente associe eventos de espera do tipo IPC a operações de consulta paralela, esse evento de espera determinado não é específico de consultas paralelas.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#apg-rpg-ipcprocarraygroup.supported)
+ [

## Contexto
](#apg-rpg-ipcprocarraygroup.context)
+ [

## Possíveis causas do maior número de esperas
](#apg-rpg-ipcprocarraygroup.causes)
+ [

## Ações
](#apg-rpg-ipcprocarraygroup.actions)

## Versões compatíveis do mecanismo
<a name="apg-rpg-ipcprocarraygroup.supported"></a>

As informações sobre esse evento de espera são aceitas em todas as versões do RDS para PostgreSQL.

## Contexto
<a name="apg-rpg-ipcprocarraygroup.context"></a>

**Noções básicas sobre a matriz do processo**: a matriz do processo (proc) é uma estrutura de memória compartilhada no PostgreSQL. Ela contém informações sobre todos os processos em execução, incluindo detalhes da transação. Durante a conclusão da transação (`COMMIT` ou `ROLLBACK`), o ProcArray precisa ser atualizado para refletir a alteração e limpar o ID da transação da matriz. A sessão que tenta concluir sua transação deve adquirir um bloqueio exclusivo no ProcArray. Isso impede que outros processos tenham bloqueios compartilhados ou exclusivos.

**Mecanismo de atualização de grupo**: ao executar um COMMIT ou ROLLBACK, se um processo de backend não conseguir recuperar um ProcArrayLock no modo exclusivo, ele atualizará um campo especial chamado ProcArrayGroupMember. Isso adiciona a transação à lista de sessões que pretendem terminar. Esse processo de backend então é suspenso, e o tempo de suspensão é instrumentado como o evento de espera ProcArrayGroupUpdate. O primeiro processo no ProcArray com o procArrayGroupMember, conhecido como processo líder, adquire o ProcArrayLock no modo exclusivo. Depois, ele limpa a lista de processos que aguardam a limpeza do transactionID do grupo. Quando isso é concluído, o líder libera o ProcArrayLock e, depois, ativa todos os processos dessa lista, notificando-os de que a transação foi concluída.

## Possíveis causas do maior número de esperas
<a name="apg-rpg-ipcprocarraygroup.causes"></a>

Quanto mais processos estiverem em execução, mais tempo um líder manterá um procArrayLock no modo exclusivo. Consequentemente, quanto mais transações de gravação ocorrerem, maior a chance de entrarem em um cenário de atualização em grupo, causando um possível acúmulo de processos aguardando o evento de espera `ProcArrayGroupUpdate`. Na visualização Top SQL do Database Insights, você verá que COMMIT é a declaração com a maior parte desse evento de espera. Isso é esperado, mas exigirá uma investigação mais profunda do SQL de gravação específico que está sendo executado para determinar qual ação apropriada realizar.

## Ações
<a name="apg-rpg-ipcprocarraygroup.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera. Identifique eventos `IPC:ProcArrayGroupUpdate` utilizando o Insights de Performance do Amazon RDS ou consultando a visualização `pg_stat_activity` do sistema PostgreSQL.

**Topics**
+ [

### Monitorar operações de confirmação e reversão de transações
](#apg-rpg-ipcprocarraygroup.actions.monitor)
+ [

### Reduzir a simultaneidade
](#apg-rpg-ipcprocarraygroup.actions.concurrency)
+ [

### Implementar o agrupamento de conexões
](#apg-rpg-ipcprocarraygroup.actions.pooling)
+ [

### Usar um armazenamento mais rápido
](#apg-rpg-ipcprocarraygroup.actions.storage)

### Monitorar operações de confirmação e reversão de transações
<a name="apg-rpg-ipcprocarraygroup.actions.monitor"></a>

**Monitorar confirmações e reversões**: um número maior de confirmações e reversões pode aumentar a pressão sobre o ProcArray. Por exemplo, se uma instrução SQL começar a falhar devido ao aumento das violações de chaves duplicadas, você poderá observar um aumento nas reversões, o que pode aumentar a contenção do ProcArray e o inchaço da tabela.

O Amazon RDS Database Insights fornece as métricas `xact_commit` e `xact_rollback` do PostgreSQL e relata o número de confirmações e reversões por segundo.

### Reduzir a simultaneidade
<a name="apg-rpg-ipcprocarraygroup.actions.concurrency"></a>

**Transações em lote**: sempre que possível, agrupe operações em transações únicas para reduzir as operações de confirmação/reversão.

**Limitar a simultaneidade**: reduza o número de transações ativas simultaneamente para aliviar a contenção de bloqueios no ProcArray. Embora isso exija alguns testes, reduzir o número total de conexões simultâneas pode reduzir a contenção e manter o throughput.

### Implementar o agrupamento de conexões
<a name="apg-rpg-ipcprocarraygroup.actions.pooling"></a>

**Soluções de agrupamento de conexões**: use o grupo de conexões para gerenciar conexões de banco de dados com eficiência, reduzindo o número total de backends e, portanto, a workload no ProcArray. Embora isso exija alguns testes, reduzir o número total de conexões simultâneas pode reduzir a contenção e manter o throughput.

**Reduzir os surtos de conexão**: da mesma forma, um padrão de criação e encerramento frequentes de conexões causa pressão adicional no ProcArray. Ao reduzir esse padrão, a contenção geral é reduzida.

### Usar um armazenamento mais rápido
<a name="apg-rpg-ipcprocarraygroup.actions.storage"></a>

**Volume de log dedicado**: se o evento de espera `IPC:ProcArrayGroupUpdate` for acompanhado por eventos de alta espera `IO:WALWrite`, a configuração de um volume de logs dedicado poderá reduzir o gargalo de gravação no WAL. Por sua vez, isso melhora a performance das confirmações.

Para acessar mais informações, consulte [Volume de logs dedicado](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PIOPS.dlv.html).

# Lock:advisory
<a name="wait-event.lockadvisory"></a>

O evento `Lock:advisory` ocorre quando uma aplicação PostgreSQL utiliza um bloqueio para coordenar as atividades em várias sessões.

**Topics**
+ [

## Versões de mecanismos relevantes
](#wait-event.lockadvisory.context.supported)
+ [

## Contexto
](#wait-event.lockadvisory.context)
+ [

## Causas
](#wait-event.lockadvisory.causes)
+ [

## Ações
](#wait-event.lockadvisory.actions)

## Versões de mecanismos relevantes
<a name="wait-event.lockadvisory.context.supported"></a>

As informações sobre eventos de espera são relevantes para o RDS para PostgreSQL versão 9.6 e versões superiores.

## Contexto
<a name="wait-event.lockadvisory.context"></a>

Bloqueios consultivos do PostgreSQL são bloqueios cooperativos em nível de aplicação, feitos explicitamente e desfeitos pelo código da aplicação do usuário. Uma aplicação pode utilizar bloqueios consultivos do PostgreSQL para coordenar atividades em várias sessões. Ao contrário de bloqueios regulares, ou em nível de objeto ou linha, a aplicação tem controle total ao longo da vida útil do bloqueio. Para obter mais informações, consulte o tópico sobre [Bloqueios consultivos](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS) na documentação do PostgreSQL.

Bloqueios consultivos podem ser liberados antes que uma transação termine ou podem ser mantidos por uma sessão em todas as transações. Isso não é válido para bloqueios implícitos aplicados pelo sistema, como um bloqueio exclusivo de acesso em uma tabela adquirida por uma instrução `CREATE INDEX`.

Para obter uma descrição das funções utilizadas para adquirir (bloquear) e liberar (desbloquear) bloqueios consultivos, consulte o tópico sobre [Funções de bloqueios consultivos](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS), na documentação do PostgreSQL.

Bloqueios consultivos são implementados sobre o sistema de bloqueio regular do PostgreSQL e ficam visíveis na visualização do sistema `pg_locks`.

## Causas
<a name="wait-event.lockadvisory.causes"></a>

Esse tipo de bloqueio é controlado exclusivamente por uma aplicação que o utiliza explicitamente. Bloqueios consultivos que são adquiridos para cada linha como parte de uma consulta podem causar um aumento nos bloqueios ou um acúmulo a longo prazo.

Esses efeitos acontecem quando a consulta é executada de uma maneira que adquire bloqueios em mais linhas do que as retornadas pela consulta. A aplicação deve eventualmente liberar todos os bloqueios, mas, se eles forem adquiridos em linhas que não são retornadas, a aplicação não poderá localizar todos os bloqueios.

O exemplo a seguir foi extraído do tópico [Bloqueios consultivos](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS) na documentação do PostgreSQL.

```
SELECT pg_advisory_lock(id) FROM foo WHERE id > 12345 LIMIT 100;
```

Nesse exemplo, a cláusula `LIMIT` apenas pode interromper a saída da consulta depois que as linhas já foram selecionadas internamente e seus valores de ID estão bloqueados. Isso pode acontecer repentinamente quando um volume de dados crescente faz com que o planejador escolha um plano de execução diferente que não foi testado durante o desenvolvimento. O acúmulo nesse caso acontece porque a aplicação chama explicitamente `pg_advisory_unlock` para cada valor de ID bloqueado. No entanto, nesse caso, não é possível encontrar o conjunto de bloqueios adquiridos em linhas que não foram retornadas. Como os bloqueios são adquiridos em nível de sessão, eles não são liberados automaticamente no final da transação.

Outra possível causa para picos em tentativas de bloqueio bloqueadas são conflitos não intencionais. Nesses conflitos, partes não relacionadas da aplicação compartilham o mesmo espaço de ID de bloqueio por engano.

## Ações
<a name="wait-event.lockadvisory.actions"></a>

Revise o uso da aplicação de bloqueios consultivos e detalhe onde e quando no fluxo de aplicação cada tipo de bloqueio consultivo é adquirido e liberado.

Determine se uma sessão está adquirindo muitos bloqueios ou se uma sessão de longa execução não está liberando bloqueios cedo o suficiente, resultando em um acúmulo lento de bloqueios. Você pode corrigir um acúmulo lento de bloqueios em nível de sessão encerrando a sessão com `pg_terminate_backend(pid)`. 

Um cliente que aguarda um bloqueio de consultoria aparece em `pg_stat_activity` com `wait_event_type=Lock` e `wait_event=advisory`. É possível obter valores de bloqueio específicos consultando a visualização do sistema `pg_locks` em busca do mesmo `pid`, procurando `locktype=advisory` e `granted=f`.

Em seguida, identifique a sessão de bloqueio consultando `pg_locks` em busca do mesmo bloqueio consultivo que possui `granted=t`, conforme mostrado no exemplo a seguir.

```
SELECT blocked_locks.pid AS blocked_pid,
         blocking_locks.pid AS blocking_pid,
         blocked_activity.usename AS blocked_user,
         blocking_activity.usename AS blocking_user,
         now() - blocked_activity.xact_start AS blocked_transaction_duration,
         now() - blocking_activity.xact_start AS blocking_transaction_duration,
         concat(blocked_activity.wait_event_type,':',blocked_activity.wait_event) AS blocked_wait_event,
         concat(blocking_activity.wait_event_type,':',blocking_activity.wait_event) AS blocking_wait_event,
         blocked_activity.state AS blocked_state,
         blocking_activity.state AS blocking_state,
         blocked_locks.locktype AS blocked_locktype,
         blocking_locks.locktype AS blocking_locktype,
         blocked_activity.query AS blocked_statement,
         blocking_activity.query AS blocking_statement
    FROM pg_catalog.pg_locks blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks blocking_locks
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
    WHERE NOT blocked_locks.GRANTED;
```

Todas as funções de API de bloqueio consultivo têm dois conjuntos de argumentos, um argumento `bigint` ou dois argumentos `integer`:
+ Para as funções de API com um único argumento `bigint`, os 32 bits superiores estão em `pg_locks.classid` e os 32 bits inferiores estão em `pg_locks.objid`.
+ Para as funções da API com dois argumentos `integer`, o primeiro argumento é `pg_locks.classid` e o segundo é `pg_locks.objid`.

O valor `pg_locks.objsubid` indica qual formato de API foi utilizado: `1` significa um argumento `bigint`; `2`significa dois argumentos `integer`.

# Lock:extend
<a name="wait-event.lockextend"></a>

O evento `Lock:extend` ocorre quando um processo de backend está aguardando para bloquear uma relação com o objetivo de a estender, enquanto outro processo tem um bloqueio nessa relação para o mesmo objetivo.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.lockextend.context.supported)
+ [

## Contexto
](#wait-event.lockextend.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.lockextend.causes)
+ [

## Ações
](#wait-event.lockextend.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.lockextend.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.lockextend.context"></a>

O evento `Lock:extend` indica que um processo de backend está aguardando para estender uma relação na qual outro processo de backend mantém um bloqueio enquanto estende essa relação. Como apenas um processo por vez pode estender uma relação, o sistema gera um evento de espera `Lock:extend`. Operações `INSERT`, `COPY` e `UPDATE` podem gerar esse evento.

## Possíveis causas do maior número de esperas
<a name="wait-event.lockextend.causes"></a>

Quando o evento `Lock:extend` aparece mais que o normal, possivelmente indicando um problema de performance, as causas típicas incluem:

**Surto de inserções simultâneas ou atualizações na mesma tabela **  
Pode haver um aumento no número de sessões simultâneas com consultas que inserem ou atualizam a mesma tabela.

**Largura de banda da rede insuficiente**  
É possível que a largura de banda da rede na instância de banco de dados para as necessidades de comunicação de armazenamento da workload atual. Isso pode contribuir para a latência de armazenamento que causa um aumento em eventos `Lock:extend`.

## Ações
<a name="wait-event.lockextend.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera.

**Topics**
+ [

### Reduzir inserções e atualizações simultâneas para a mesma relação
](#wait-event.lockextend.actions.action1)
+ [

### Aumentar a largura de banda da rede
](#wait-event.lockextend.actions.increase-network-bandwidth)

### Reduzir inserções e atualizações simultâneas para a mesma relação
<a name="wait-event.lockextend.actions.action1"></a>

Primeiro, determine se há um aumento nas métricas `tup_inserted` e `tup_updated` e um aumento acompanhante nesse evento de espera. Em caso afirmativo, verifique quais relações estão em alta disputa por operações de inserção e atualização. Para determinar isso, consulte a visualização `pg_stat_all_tables` para os valores nos campos `n_tup_ins` e `n_tup_upd`. Para obter mais informações sobre a visualização `pg_stat_all_tables`, consulte [pg\$1stat\$1all\$1tables](https://www.postgresql.org/docs/13/monitoring-stats.html#MONITORING-PG-STAT-ALL-TABLES-VIEW) na documentação do PostgreSQL. 

Para obter mais informações sobre bloqueio e consultas bloqueadas, consulte `pg_stat_activity` como no exemplo a seguir:

```
SELECT
    blocked.pid,
    blocked.usename,
    blocked.query,
    blocking.pid AS blocking_id,
    blocking.query AS blocking_query,
    blocking.wait_event AS blocking_wait_event,
    blocking.wait_event_type AS blocking_wait_event_type
FROM pg_stat_activity AS blocked
JOIN pg_stat_activity AS blocking ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
where
blocked.wait_event = 'extend'
and blocked.wait_event_type = 'Lock';
 
   pid  | usename  |            query             | blocking_id |                         blocking_query                           | blocking_wait_event | blocking_wait_event_type
  ------+----------+------------------------------+-------------+------------------------------------------------------------------+---------------------+--------------------------
   7143 |  myuser  | insert into tab1 values (1); |        4600 | INSERT INTO tab1 (a) SELECT s FROM generate_series(1,1000000) s; | DataFileExtend      | IO
```

Depois de identificar relações que contribuem para o aumento dos eventos `Lock:extend`, utilize as seguintes técnicas para reduzir a contenção:
+ Descubra se é possível utilizar o particionamento para reduzir a contenção para a mesma tabela. Separar tuplas inseridas ou atualizadas em partições diferentes pode reduzir a contenção. Para obter informações sobre particionamento, consulte [Gerenciar partições do PostgreSQL com a extensão pg\$1partman](PostgreSQL_Partitions.md).
+ Se o evento de espera for principalmente devido a atividades de atualização, reduza o valor do fator de preenchimento da relação. Isso pode reduzir as solicitações de novos bloqueios durante a atualização. O fator de preenchimento é um parâmetro de armazenamento de uma tabela que determina o espaço máximo para empacotar uma página de tabela. Ele é expresso como uma porcentagem do espaço total de uma página. Para obter mais informações sobre o parâmetro de fator de preenchimento, consulte [CREATE TABLE](https://www.postgresql.org/docs/13/sql-createtable.html) na documentação do PostgreSQL. 
**Importante**  
É altamente recomendável testar seu sistema se você alterar o fator de preenchimento, pois isso pode afetar negativamente a performance dependendo da workload.

### Aumentar a largura de banda da rede
<a name="wait-event.lockextend.actions.increase-network-bandwidth"></a>

Para ver se há um aumento na latência de gravação, verifique a métrica `WriteLatency` no CloudWatch. Se houver, use as métricas `WriteThroughput` e `ReadThroughput` do Amazon CloudWatch para monitorar o tráfego relacionado ao armazenamento na instância de banco de dados. Essas métricas podem ajudar a determinar se a largura de banda da rede é suficiente para a atividade de armazenamento da sua workload.

Se a largura de banda da rede não suficiente, aumente-a. Se a sua instância de banco de dados estiver atingindo os limites de largura de banda da rede, a única maneira de aumentar a largura de banda será ampliar o tamanho da instância de banco de dados.

Para obter mais informações sobre métricas do CloudWatch, consulte [Métricas específicas da instância do Amazon CloudWatch para Amazon RDS](rds-metrics.md#rds-cw-metrics-instance). Para obter informações sobre a performance de rede de cada classe de instância de banco de dados, consulte [Métricas específicas da instância do Amazon CloudWatch para Amazon RDS](rds-metrics.md#rds-cw-metrics-instance). 

# Lock:Relation
<a name="wait-event.lockrelation"></a>

O evento `Lock:Relation` ocorre quando uma consulta está aguardando para adquirir um bloqueio em uma tabela ou visualização (relação) que está atualmente bloqueada por outra transação.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.lockrelation.context.supported)
+ [

## Contexto
](#wait-event.lockrelation.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.lockrelation.causes)
+ [

## Ações
](#wait-event.lockrelation.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.lockrelation.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.lockrelation.context"></a>

A maioria dos comandos PostgreSQL utiliza bloqueios implicitamente para controlar o acesso simultâneo aos dados em tabelas. Também é possível utilizar esses bloqueios explicitamente no código da aplicação com o comando `LOCK`. Vários modos de bloqueio não são compatíveis entre si e podem bloquear transações quando tentam acessar o mesmo objeto. Quando isso acontece, o RDS para PostgreSQL gera um evento `Lock:Relation`. Veja a seguir alguns exemplos comuns:
+ Bloqueios exclusivos, como `ACCESS EXCLUSIVE`, podem bloquear todo o acesso simultâneo. Operações de linguagem de definição de dados (DDL), como `DROP TABLE`, `TRUNCATE`, `VACUUM FULL` e `CLUSTER`, adquirem bloqueios `ACCESS EXCLUSIVE` implicitamente. `ACCESS EXCLUSIVE` também é o modo de bloqueio padrão para instruções `LOCK TABLE` que não especificam um modo explicitamente.
+ Usar `CREATE INDEX (without CONCURRENT)` em uma tabela gera conflito com instruções de linguagem de manipulação de dados (DML) `UPDATE`, `DELETE` e `INSERT`, que adquirem bloqueios `ROW EXCLUSIVE`.

Para obter mais informações sobre bloqueios em nível da tabela e modos de bloqueio conflitantes, consulte o tópico sobre [Bloqueio explícito](https://www.postgresql.org/docs/13/explicit-locking.html) na documentação do PostgreSQL.

Normalmente, o bloqueio de consultas e transações é liberado de uma das seguintes maneiras:
+ Consulta de bloqueio: a aplicação pode cancelar a consulta ou o usuário pode encerrar o processo. O mecanismo também pode forçar a finalização da consulta devido a um tempo limite de declaração de uma sessão ou um mecanismo de detecção de deadlock.
+ Transação de bloqueio: uma transação para de bloquear quando executa uma instrução `ROLLBACK` ou `COMMIT`. Reversões também acontecem automaticamente quando as sessões são desconectadas por um cliente ou por problemas de rede, ou quando são encerradas. As sessões podem ser encerradas quando o mecanismo de banco de dados é desligado, quando o sistema está sem memória e assim por diante.

## Possíveis causas do maior número de esperas
<a name="wait-event.lockrelation.causes"></a>

Quando o evento `Lock:Relation` ocorre com maior frequência do que o normal, pode indicar um problema de performance. As causas típicas incluem:

**Maior número de sessões simultâneas com bloqueios de tabela conflitantes**  
Pode haver um aumento no número de sessões simultâneas com consultas que bloqueiam a mesma tabela com modos de bloqueio conflitantes.

**Operações de manutenção**  
Operações de manutenção de integridade, como `VACUUM` e `ANALYZE`, podem aumentar significativamente o número de bloqueios conflitantes. `VACUUM FULL` adquire um bloqueio `ACCESS EXCLUSIVE` e `ANALYSE` adquire um bloqueio `SHARE UPDATE EXCLUSIVE`. Ambos os tipos de bloqueios podem causar um evento de espera `Lock:Relation`. Operações de manutenção de dados de aplicações, como atualizar uma visualização materializada, também podem aumentar as consultas e transações bloqueadas.

**Bloqueios em instâncias de leitor**  
Pode haver um conflito entre os bloqueios de relação mantidos pelo gravador e os leitores. No momento, só bloqueios de relação do `ACCESS EXCLUSIVE` são replicados para instâncias do leitor. No entanto, o bloqueio de relação do `ACCESS EXCLUSIVE` entrará em conflito com qualquer bloqueio de relação do `ACCESS SHARE` mantido pelo leitor. Isso pode causar um aumento nos eventos de espera de relação de bloqueio no leitor. 

## Ações
<a name="wait-event.lockrelation.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera.

**Topics**
+ [

### Reduzir o impacto do bloqueio de instruções SQL
](#wait-event.lockrelation.actions.reduce-blocks)
+ [

### Minimizar o efeito de operações de manutenção
](#wait-event.lockrelation.actions.maintenance)

### Reduzir o impacto do bloqueio de instruções SQL
<a name="wait-event.lockrelation.actions.reduce-blocks"></a>

Para reduzir o impacto do bloqueio de instruções SQL, modifique o código da aplicação sempre que possível. Veja a seguir duas técnicas comuns para reduzir bloqueios:
+ Usar a opção `NOWAIT`: alguns comandos SQL, como instruções `SELECT` e `LOCK`, oferecem suporte a essa opção. A diretiva `NOWAIT` cancela a consulta de solicitação de bloqueio quando o bloqueio não pode ser adquirido imediatamente. Essa técnica pode evitar que uma sessão de bloqueio cause um empilhamento de sessões bloqueadas por detrás dela.

  Por exemplo: suponha que a transação A esteja aguardando um bloqueio mantido pela transação B. Se B solicitar um bloqueio em uma tabela bloqueada pela transação C, a transação A poderá ser bloqueada até a conclusão da transação C. Porém, se a transação B utilizar um `NOWAIT` quando solicitar o bloqueio em C, ela pode falhar rapidamente e garantir que a transação A não precise aguardar indefinidamente.
+ Usar `SET lock_timeout`: defina um valor de `lock_timeout` para limitar o tempo de espera de uma instrução SQL para adquirir um bloqueio em uma relação. Se o bloqueio não for adquirido dentro do tempo limite definido, a transação que o está solicitando será cancelada. Defina o valor no nível da sessão.

### Minimizar o efeito de operações de manutenção
<a name="wait-event.lockrelation.actions.maintenance"></a>

Operações de manutenção, como `VACUUM` e `ANALYZE`, são importantes. Recomendamos que você não as desative ao encontrar eventos de espera `Lock:Relation` relacionados a essas operações de manutenção. As abordagens a seguir podem minimizar o efeito dessas operações:
+ Execute operações de manutenção manualmente fora do horário de pico.
+ Para reduzir esperas `Lock:Relation` causadas por tarefas de autovacuum, realize qualquer ajuste de autovacuum necessário. Para obter mais informações sobre ajuste de autovacuum, consulte [Trabalhar com o autovacuum do PostgreSQL no Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html), no *Guia do usuário do Amazon RDS*.

# Lock:transactionid
<a name="wait-event.locktransactionid"></a>

O evento `Lock:transactionid` ocorre quando uma transação está aguardando um bloqueio em nível de linha.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.locktransactionid.context.supported)
+ [

## Contexto
](#wait-event.locktransactionid.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.locktransactionid.causes)
+ [

## Ações
](#wait-event.locktransactionid.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.locktransactionid.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.locktransactionid.context"></a>

O evento `Lock:transactionid` ocorre quando uma transação está tentando adquirir um bloqueio em nível de linha já concedido a uma transação que está sendo executada simultaneamente. A sessão que mostra o evento de espera `Lock:transactionid` está bloqueada devido a esse bloqueio. Depois que a transação de bloqueio terminar em uma instrução `COMMIT` ou `ROLLBACK`, a transação bloqueada pode continuar.

A semântica de controle de simultaneidade de várias versões do RDS para PostgreSQL garante que os leitores não bloqueiem gravadores e que os gravadores não bloqueiem os leitores. Para que ocorram conflitos em nível de linha, transações de bloqueio e bloqueadas devem emitir instruções conflitantes dos seguintes tipos:
+ `UPDATE`
+ `SELECT … FOR UPDATE`
+ `SELECT … FOR KEY SHARE`

A instrução `SELECT … FOR KEY SHARE` é um caso especial. O banco de dados usa a cláusula `FOR KEY SHARE` para otimizar a performance da integridade referencial. Um bloqueio em nível de linha em uma linha pode bloquear comandos `INSERT`, `UPDATE` e `DELETE` em outras tabelas que fazem referência à linha.

## Possíveis causas do maior número de esperas
<a name="wait-event.locktransactionid.causes"></a>

Quando esse evento aparece mais do que o normal, a causa geralmente envolve instruções `UPDATE`, `SELECT … FOR UPDATE` ou `SELECT … FOR KEY SHARE` combinadas com as seguintes condições.

**Topics**
+ [

### Alta simultaneidade
](#wait-event.locktransactionid.concurrency)
+ [

### Ocioso na transação
](#wait-event.locktransactionid.idle)
+ [

### Transações de longa execução
](#wait-event.locktransactionid.long-running)

### Alta simultaneidade
<a name="wait-event.locktransactionid.concurrency"></a>

O RDS para PostgreSQL pode utilizar semântica de bloqueio granular em nível de linha. A probabilidade de conflitos em nível de linha aumenta quando as condições a seguir são atendidas:
+ Uma workload altamente simultânea controla as mesmas linhas.
+ A simultaneidade aumenta.

### Ocioso na transação
<a name="wait-event.locktransactionid.idle"></a>

Às vezes, a coluna `pg_stat_activity.state` mostra o valor `idle in transaction`. Esse valor aparece para sessões que iniciaram uma transação, mas ainda não emitiram um `COMMIT` ou `ROLLBACK`. Se o valor de `pg_stat_activity.state` não for `active`, a consulta mostrada em `pg_stat_activity` será a mais recente a terminar a execução. A sessão de bloqueio não está processando uma consulta ativamente porque uma transação aberta está mantendo um bloqueio.

Se uma transação ociosa adquiriu um bloqueio em nível de linha, talvez ela esteja impedindo que outras sessões o adquiram. Essa condição leva à ocorrência frequente do evento de espera `Lock:transactionid`. Para diagnosticar o problema, examine a saída proveniente de `pg_stat_activity` e `pg_locks`.

### Transações de longa execução
<a name="wait-event.locktransactionid.long-running"></a>

Transações executadas por um longo tempo recebem bloqueios por um longo tempo. Esses bloqueios de longa duração podem impedir que outras transações sejam executadas.

## Ações
<a name="wait-event.locktransactionid.actions"></a>

O bloqueio de linhas é um conflito entre instruções `UPDATE`, `SELECT … FOR UPDATE` ou `SELECT … FOR KEY SHARE`. Antes de tentar uma solução, descubra quando essas instruções estão sendo executadas na mesma linha. Use essas informações para escolher uma estratégia descrita nas seguintes seções.

**Topics**
+ [

### Responder a alta simultaneidade
](#wait-event.locktransactionid.actions.problem)
+ [

### Responder a transações ociosas
](#wait-event.locktransactionid.actions.find-blocker)
+ [

### Responder a transações de longa duração
](#wait-event.locktransactionid.actions.concurrency)

### Responder a alta simultaneidade
<a name="wait-event.locktransactionid.actions.problem"></a>

Se a simultaneidade for o problema, tente uma das seguintes técnicas:
+ Reduza a simultaneidade na aplicação. Por exemplo, reduza o número de sessões ativas.
+ Implemente um pool de conexões. Para saber como agrupar conexões com o RDS Proxy, consulte [Amazon RDS Proxy](rds-proxy.md).
+ Projete a aplicação ou o modelo de dados para evitar a contenção de instruções `UPDATE` e `SELECT … FOR UPDATE`. Também é possível diminuir o número de chaves estrangeiras acessadas por instruções `SELECT … FOR KEY SHARE`.

### Responder a transações ociosas
<a name="wait-event.locktransactionid.actions.find-blocker"></a>

Se `pg_stat_activity.state` mostrar `idle in transaction`, utilize as seguintes estratégias:
+ Ative a confirmação automática sempre que possível. Essa abordagem impede que transações bloqueiem outras transações enquanto aguardam `COMMIT` ou `ROLLBACK`.
+ Procure caminhos de código que não contenham `COMMIT`, `ROLLBACK` ou `END`.
+ Assegure-se de que a lógica de tratamento de exceções na seu aplicação sempre tenha um caminho para um válido `end of transaction`.
+ Assegure-se de que a sua aplicação processe os resultados da consulta depois de encerrar a transação com `COMMIT` ou `ROLLBACK`.

### Responder a transações de longa duração
<a name="wait-event.locktransactionid.actions.concurrency"></a>

Se transações de longa duração estiverem causando a ocorrência frequente de `Lock:transactionid`, tente as estratégias a seguir:
+ Mantenha os bloqueios de linha fora de transações de longa execução.
+ Limite o comprimento das consultas implementando a confirmação automática sempre que possível.

# Lock:tuple
<a name="wait-event.locktuple"></a>

O evento `Lock:tuple` ocorre quando um processo de backend está aguardando para adquirir um bloqueio em uma tupla.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.locktuple.context.supported)
+ [

## Contexto
](#wait-event.locktuple.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.locktuple.causes)
+ [

## Ações
](#wait-event.locktuple.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.locktuple.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.locktuple.context"></a>

O evento `Lock:tuple` indica que um backend está aguardando para adquirir um bloqueio em uma tupla enquanto outro backend mantém um bloqueio conflitante na mesma tupla. A tabela a seguir ilustra um cenário em que as sessões geram o evento `Lock:tuple`.


|  Tempo  |  Sessão 1  |  Sessão 2  |  Sessão 3  | 
| --- | --- | --- | --- | 
|  t1  |  Inicia uma transação.  |    |    | 
|  t2  |  Atualiza a linha 1.  |    |    | 
|  t3  |    |  Atualiza a linha 1. A sessão adquire um bloqueio exclusivo na tupla e aguarda a sessão 1 liberar esse bloqueio via confirmação ou reversão.  |    | 
|  t4  |    |    |  Atualiza a linha 1. A sessão aguarda a sessão 2 liberar o bloqueio exclusivo na tupla.  | 

Outra alternativa é simular esse evento de espera utilizando a ferramenta de benchmarking `pgbench`. Configure um número elevado de sessões simultâneas para atualizar a mesma linha em uma tabela com um arquivo SQL personalizado.

Para saber mais sobre modos de bloqueio conflitantes, consulte o tópico sobre [Bloqueio explícito](https://www.postgresql.org/docs/current/explicit-locking.html), na documentação do PostgreSQL. Para saber mais sobre `pgbench`, consulte [pgbench](https://www.postgresql.org/docs/current/pgbench.html) na documentação do PostgreSQL.

## Possíveis causas do maior número de esperas
<a name="wait-event.locktuple.causes"></a>

Quando esse evento aparece mais que o normal, possivelmente indicando um problema de performance, as causas típicas incluem:
+ Um número elevado de sessões simultâneas está tentando adquirir um bloqueio conflitante para a mesma tupla executando instruções `UPDATE` ou `DELETE`.
+ Sessões altamente simultâneas estão executando uma instrução `SELECT` utilizando os modos de bloqueio `FOR UPDATE` ou `FOR NO KEY UPDATE`.
+ Diversos fatores fazem com que grupos de aplicações ou conexões abram mais sessões para executar as mesmas operações. À medida que novas sessões estão tentando modificar as mesmas linhas, a carga de banco de dados pode atingir picos e `Lock:tuple` pode surgir.

Para obter mais informações, consulte o tópico sobre [Bloqueios em nível de linha](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS), na documentação do PostgreSQL.

## Ações
<a name="wait-event.locktuple.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera.

**Topics**
+ [

### Investigar a lógica da sua aplicação
](#wait-event.locktuple.actions.problem)
+ [

### Localizar a sessão bloqueadora
](#wait-event.locktuple.actions.find-blocker)
+ [

### Reduzir a simultaneidade quando ela estiver elevada
](#wait-event.locktuple.actions.concurrency)
+ [

### Solucionar problemas de gargalos
](#wait-event.locktuple.actions.bottlenecks)

### Investigar a lógica da sua aplicação
<a name="wait-event.locktuple.actions.problem"></a>

Descubra se uma sessão bloqueadora está no estado `idle in transaction` por muito tempo. Em caso positivo, considere encerrar a sessão bloqueadora como uma solução de curto prazo. Também é possível utilizar a função `pg_terminate_backend`. Para obter mais informações sobre essa função, consulte [Funções de sinalização de servidor](https://www.postgresql.org/docs/13/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL), na documentação do PostgreSQL.

Para uma solução de longo prazo, faça o seguinte:
+ Ajuste a lógica da aplicação.
+ Use o parâmetro `idle_in_transaction_session_timeout`. Esse parâmetro encerra qualquer sessão com uma transação aberta que tenha ficado ociosa por um tempo maior que o especificado. Para obter mais informações, consulte o tópico sobre [Padrões de conexão de clientes](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT), na documentação do PostgreSQL.
+ Use a confirmação automática o máximo possível. Para obter mais informações, consulte [SET AUTOCOMMIT](https://www.postgresql.org/docs/current/ecpg-sql-set-autocommit.html), na documentação do PostgreSQL.

### Localizar a sessão bloqueadora
<a name="wait-event.locktuple.actions.find-blocker"></a>

Enquanto o evento de espera `Lock:tuple` está ocorrendo, identifique a sessão bloqueadora e a sessão bloqueada descobrindo quais bloqueios dependem um do outro. Para obter mais informações, consulte o tópico sobre [Informações de dependências de bloqueios](https://wiki.postgresql.org/wiki/Lock_dependency_information), na wiki do PostgreSQL. 

O exemplo a seguir consulta todas as sessões, filtrando em `tuple` e ordenando por `wait_time`.

```
SELECT blocked_locks.pid AS blocked_pid,
         blocking_locks.pid AS blocking_pid,
         blocked_activity.usename AS blocked_user,
         blocking_activity.usename AS blocking_user,
         now() - blocked_activity.xact_start AS blocked_transaction_duration,
         now() - blocking_activity.xact_start AS blocking_transaction_duration,
         concat(blocked_activity.wait_event_type,':',blocked_activity.wait_event) AS blocked_wait_event,
         concat(blocking_activity.wait_event_type,':',blocking_activity.wait_event) AS blocking_wait_event,
         blocked_activity.state AS blocked_state,
         blocking_activity.state AS blocking_state,
         blocked_locks.locktype AS blocked_locktype,
         blocking_locks.locktype AS blocking_locktype,
         blocked_activity.query AS blocked_statement,
         blocking_activity.query AS blocking_statement
    FROM pg_catalog.pg_locks blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks blocking_locks
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
    WHERE NOT blocked_locks.GRANTED;
```

### Reduzir a simultaneidade quando ela estiver elevada
<a name="wait-event.locktuple.actions.concurrency"></a>

O evento `Lock:tuple` pode ocorrer constantemente, especialmente em um tempo de workload ocupado. Nessa situação, considere reduzir a simultaneidade elevada para linhas muito ocupadas. Várias vezes, apenas algumas linhas controlam uma fila ou a lógica booleana, o que torna essas linhas muito ocupadas.

Você pode reduzir a simultaneidade utilizando diferentes abordagens com base no seu requisito de negócios, na lógica da aplicação e no tipo de workload. Por exemplo, você pode fazer o seguinte:
+ Reformule sua tabela e a lógica de dados para reduzir a simultaneidade elevada.
+ Altere a lógica da aplicação para reduzir a simultaneidade elevada no nível da linha.
+ Aproveite e reformule consultas com bloqueios em nível de linha.
+ Use a cláusula `NOWAIT` com operações de novas tentativas.
+ Considere utilizar o controle de simultaneidade lógico otimista e bloqueio híbrido.
+ Considere modificar o nível de isolamento do banco de dados.

### Solucionar problemas de gargalos
<a name="wait-event.locktuple.actions.bottlenecks"></a>

O `Lock:tuple` pode ocorrer com gargalos, como falta de CPU ou uso máximo da largura de banda do Amazon EBS. Para diminuir gargalos, considere as seguintes abordagens:
+ Aumente a escala do seu tipo de classe de instância na vertical.
+ Otimize consultas que consomem muitos recursos.
+ Altere a lógica da aplicação.
+ Arquive dados acessados raramente.

# LWLock:BufferMapping (LWLock:buffer\$1mapping)
<a name="wait-event.lwl-buffer-mapping"></a>

Esse evento ocorre quando uma sessão está aguardando para associar um bloco de dados a um buffer no grupo de buffer compartilhado.

**nota**  
Esse evento é denominado `LWLock:BufferMapping` para o RDS para PostgreSQL versão 13 e posteriores. No caso do RDS para PostgreSQL versão 12 e posteriores, esse evento é denominado `LWLock:buffer_mapping`. 

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.lwl-buffer-mapping.context.supported)
+ [

## Contexto
](#wait-event.lwl-buffer-mapping.context)
+ [

## Causas
](#wait-event.lwl-buffer-mapping.causes)
+ [

## Ações
](#wait-event.lwl-buffer-mapping.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.lwl-buffer-mapping.context.supported"></a>

As informações de eventos de espera são relevantes para o RDS para PostgreSQL versão 9.6 e posteriores.

## Contexto
<a name="wait-event.lwl-buffer-mapping.context"></a>

O *grupo de buffer compartilhado* é uma área de memória do PostgreSQL que contém todas as páginas que estão ou estavam sendo utilizadas por processos. Quando um processo precisa de uma página, ele lê a página no grupo de buffer compartilhado. O parâmetro `shared_buffers` define o tamanho do buffer compartilhado e reserva uma área de memória para armazenar a tabela e as páginas de índice. Se você alterar esse parâmetro, reinicie o banco de dados.

O evento de espera `LWLock:buffer_mapping` ocorre nos seguintes cenários:
+ Um processo pesquisa a tabela de buffer em busca de uma página e adquire um bloqueio de mapeamento de buffer compartilhado.
+ Um processo carrega uma página no grupo de buffer e adquire um bloqueio exclusivo de mapeamento de buffer.
+ Um processo remove uma página do grupo e adquire um bloqueio exclusivo de mapeamento de buffer.

## Causas
<a name="wait-event.lwl-buffer-mapping.causes"></a>

Quando esse evento aparece mais do que o normal, possivelmente indicando um problema de performance, o banco de dados está paginando dentro e fora do grupo de buffer compartilhado. As causas típicas incluem:
+ Consultas grandes
+ Índices e tabelas inchados
+ Varreduras completas de tabelas
+ Um tamanho de grupo compartilhado menor que o conjunto de trabalho

## Ações
<a name="wait-event.lwl-buffer-mapping.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera.

**Topics**
+ [

### Monitorar métricas relacionadas ao buffer
](#wait-event.lwl-buffer-mapping.actions.monitor-metrics)
+ [

### Avaliar sua estratégia de indexação
](#wait-event.lwl-buffer-mapping.actions.indexes)
+ [

### Diminuir o número de buffers que devem ser alocados rapidamente
](#wait-event.lwl-buffer-mapping.actions.buffers)

### Monitorar métricas relacionadas ao buffer
<a name="wait-event.lwl-buffer-mapping.actions.monitor-metrics"></a>

Quando as esperas `LWLock:buffer_mapping` atingirem picos, investigue a taxa de acertos de buffer. É possível utilizar essas métricas para entender melhor o que está acontecendo no cache de buffer. Examine as métricas a seguir:

`blks_hit`  
Essa métrica de contador do Performance Insights indica o número de bloqueios que foram recuperados do grupo de buffer compartilhado. Após o surgimento do evento de espera `LWLock:buffer_mapping`, é possível observar um pico em `blks_hit`.

`blks_read`  
Essa métrica de contador do Performance Insights indica o número de bloqueios que exigiram a leitura da E/S no grupo de buffer compartilhado. Você pode observar um pico em `blks_read` em preparação para o evento de espera `LWLock:buffer_mapping`.

### Avaliar sua estratégia de indexação
<a name="wait-event.lwl-buffer-mapping.actions.indexes"></a>

Para confirmar que sua estratégia de indexação não está diminuindo a performance, verifique o seguinte:

Inchaço de índice  
Assegure-se de que o índice e o inchaço da tabela não estejam fazendo com que páginas desnecessárias sejam lidas no buffer compartilhado. Se as suas tabelas contiverem linhas não utilizadas, considere arquivar os dados e remover as linhas das tabelas. Em seguida, você poderá reconstruir os índices para as tabelas redimensionadas.

Índices para consultas utilizadas com frequência  
Para determinar se você tem os índices ideais, monitore as métricas do mecanismo de banco de dados no Performance Insights. A métrica `tup_returned` mostra o número de linhas lidas. A métrica `tup_fetched` mostra o número de linhas retornadas ao cliente. Se `tup_returned` for significativamente maior que `tup_fetched`, talvez os dados não estejam devidamente indexados. Além disso, as estatísticas da tabela podem não estar atualizadas.

### Diminuir o número de buffers que devem ser alocados rapidamente
<a name="wait-event.lwl-buffer-mapping.actions.buffers"></a>

Para diminuir os eventos de espera `LWLock:buffer_mapping`, tente reduzir o número de buffers que devem ser alocados rapidamente. Uma estratégia é realizar operações em lote menores. Talvez seja possível obter lotes menores particionando tabelas.

# LWLock:BufferIO (IPC:BufferIO)
<a name="wait-event.lwlockbufferio"></a>

O evento `LWLock:BufferIO` ocorre quando o RDS para PostgreSQL aguarda outros processos terminarem suas operações de entrada/saída (E/S) ao tentarem acessar simultaneamente uma página. Sua finalidade é fazer com que a mesma página seja lida no buffer compartilhado.

**Topics**
+ [

## Versões de mecanismos relevantes
](#wait-event.lwlockbufferio.context.supported)
+ [

## Contexto
](#wait-event.lwlockbufferio.context)
+ [

## Causas
](#wait-event.lwlockbufferio.causes)
+ [

## Ações
](#wait-event.lwlockbufferio.actions)

## Versões de mecanismos relevantes
<a name="wait-event.lwlockbufferio.context.supported"></a>

Essas informações de evento de espera são relevantes para todas as versões do RDS para PostgreSQL. Para o RDS para PostgreSQL 12 e versões anteriores, esse evento de espera é denominado lwlock:buffer\$1io, ao passo que, no RDS para PostgreSQL 13, ele é denominado lwlock:bufferio. A partir do RDS para PostgreSQL 14, o evento de espera BufferIO mudou do tipo de evento de espera `LWLock` para `IPC` (IPC:BufferIO). 

## Contexto
<a name="wait-event.lwlockbufferio.context"></a>

Cada buffer compartilhado tem um bloqueio de E/S associado ao evento de espera `LWLock:BufferIO`, todas as vezes que um bloqueio (ou uma página) precisa ser recuperado fora do grupo de buffer compartilhado.

Esse bloqueio é utilizado para lidar com várias sessões que requerem acesso ao mesmo bloco. Esse bloco precisa ser lido de fora do grupo de buffer compartilhado, definido pelo parâmetro `shared_buffers`.

Assim que a página for lida dentro do grupo de buffer compartilhado, o bloqueio de `LWLock:BufferIO` será liberado.

**nota**  
O evento de espera `LWLock:BufferIO` precede o evento de espera [IO:DataFileRead](wait-event.iodatafileread.md). O evento de espera `IO:DataFileRead` ocorre enquanto os dados estão sendo lidos do armazenamento.

Para obter mais informações sobre bloqueios leves, consulte [Visão geral de bloqueios](https://github.com/postgres/postgres/blob/65dc30ced64cd17f3800ff1b73ab1d358e92efd8/src/backend/storage/lmgr/README#L20).

## Causas
<a name="wait-event.lwlockbufferio.causes"></a>

Causas comuns do surgimento do evento `LWLock:BufferIO` nas principais esperas incluem:
+ Vários backends ou conexões tentando acessar a mesma página para a qual também há uma operação de E/S pendente
+ A proporção entre o tamanho do grupo de buffer compartilhado (definido pelo parâmetro `shared_buffers`) e o número de buffers necessários para a workload atual
+ O tamanho do grupo de buffer compartilhado não está bem equilibrado com o número de páginas que estão sendo despejadas por outras operações
+ Índices grandes ou inchados que exigem que o mecanismo leia mais páginas que o necessário no grupo de buffer compartilhado
+ Ausência índices, o que força o mecanismo de banco de dados a ler mais páginas das tabelas que o necessário
+ Pontos de verificação ocorrendo com muita frequência ou que precisam liberar muitas páginas modificadas
+ Picos repentinos de conexões de banco de dados tentando realizar operações na mesma página

## Ações
<a name="wait-event.lwlockbufferio.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera:
+ Observe as métricas do Amazon CloudWatch para encontrar uma correlação entre reduções acentuadas nos eventos de espera `BufferCacheHitRatio` e `LWLock:BufferIO`. Esse efeito pode significar que existe uma pequena configuração de buffers compartilhados. Talvez seja necessário aumentá-lo ou aumentar a escala da classe de instância de banco de dados na vertical. Você pode dividir sua workload em mais nós de leitura.
+ Ajuste `max_wal_size` e `checkpoint_timeout` com base no horário de pico da workload, se você vir `LWLock:BufferIO` correspondendo a quedas da métrica `BufferCacheHitRatio`. Em seguida, identifique qual consulta pode estar causando isso.
+ Verifique se existem índices não utilizados e remova-os.
+ Use tabelas particionadas (que também tenham índices particionados). Fazer isso ajuda a manter a reordenação do índice baixo e reduz seu impacto.
+ Evite indexar colunas desnecessariamente.
+ Evite picos repentinos de conexão de banco de dados utilizando um grupo de conexões.
+ Restrinja o número máximo de conexões com o banco de dados como prática recomendada.

# LWLock:buffer\$1content (BufferContent)
<a name="wait-event.lwlockbuffercontent"></a>

O evento `LWLock:buffer_content` ocorre quando uma sessão aguarda para ler ou gravar uma página de dados na memória enquanto outra sessão fica com a página bloqueada para gravação. No RDS para PostgreSQL 13 e versões superiores, esse evento de espera é chamado de `BufferContent`.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.lwlockbuffercontent.context.supported)
+ [

## Contexto
](#wait-event.lwlockbuffercontent.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.lwlockbuffercontent.causes)
+ [

## Ações
](#wait-event.lwlockbuffercontent.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.lwlockbuffercontent.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.lwlockbuffercontent.context"></a>

Para ler ou manipular dados, o PostgreSQL os acessa por meio de buffers de memória compartilhada. Para ler a partir do buffer, um processo obtém um bloqueio leve (LWLock) no conteúdo do buffer no modo compartilhado. Para gravar no buffer, ele adquire esse bloqueio no modo exclusivo. Bloqueios compartilhados permitem que outros processos adquiram bloqueios compartilhados simultaneamente nesse conteúdo. Bloqueios exclusivos impedem que outros processos obtenham qualquer tipo de bloqueio nele.

O evento `LWLock:buffer_content` (`BufferContent`) indica que vários processos estão tentando obter um bloqueio no conteúdo de um buffer específico.

## Possíveis causas do maior número de esperas
<a name="wait-event.lwlockbuffercontent.causes"></a>

Quando o evento `LWLock:buffer_content` (`BufferContent`) aparece mais que o normal, possivelmente indicando um problema de performance, as causas típicas incluem:

**Maior número de atualizações simultâneas para os mesmos dados**  
Pode haver um aumento no número de sessões simultâneas com consultas que atualizam o mesmo conteúdo do buffer. Essa contenção pode ser mais evidente em tabelas com vários índices.

**Os dados da workload não estão na memória**  
Quando os dados que a workload ativa está processando não estão na memória, esses eventos de espera podem aumentar. Esse efeito ocorre porque os processos que mantêm bloqueios podem fazer isso por mais tempo enquanto executam operações de E/S de disco.

**Uso excessivo de restrições de chaves externas**  
Restrições de chave externas podem aumentar o tempo durante o qual um processo mantém um bloqueio de conteúdo de buffer. Esse efeito ocorre porque operações de leitura exigem um bloqueio de conteúdo de buffer compartilhado na chave referenciada enquanto esta está sendo atualizada.

## Ações
<a name="wait-event.lwlockbuffercontent.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera. Você pode identificar eventos `LWLock:buffer_content` (`BufferContent`) utilizando o Amazon RDS Performance Insights ou consultando a visualização `pg_stat_activity`.

**Topics**
+ [

### Melhorar a eficiência na memória
](#wait-event.lwlockbuffercontent.actions.in-memory)
+ [

### Reduzir o uso de restrições de chaves externas
](#wait-event.lwlockbuffercontent.actions.foreignkey)
+ [

### Remover índices não utilizados
](#wait-event.lwlockbuffercontent.actions.indexes)
+ [

### Aumentar o tamanho do cache ao usar sequências
](#wait-event.lwlockbuffercontent.actions.sequences)

### Melhorar a eficiência na memória
<a name="wait-event.lwlockbuffercontent.actions.in-memory"></a>

Para aumentar as chances de que os dados da workload ativa estejam na memória, particione tabelas ou aumente a escala da sua classe de instância na vertical. Para obter informações sobre classes de instância de banco de dados, consulte [Classes de instâncias de banco de dados do ](Concepts.DBInstanceClass.md).

### Reduzir o uso de restrições de chaves externas
<a name="wait-event.lwlockbuffercontent.actions.foreignkey"></a>

Investigue workloads com um número elevado de eventos de espera `LWLock:buffer_content` (`BufferContent`) quanto ao uso de restrições de chaves externas. Remova restrições desnecessárias de chaves externas.

### Remover índices não utilizados
<a name="wait-event.lwlockbuffercontent.actions.indexes"></a>

Para workloads com um número elevado de eventos de espera `LWLock:buffer_content` (`BufferContent`), identifique índices não utilizados e remova-os.

### Aumentar o tamanho do cache ao usar sequências
<a name="wait-event.lwlockbuffercontent.actions.sequences"></a>

Se suas tabelas usarem sequências, aumente o tamanho do cache para remover a contenção nas páginas de sequência e nas páginas de índice. Cada sequência é uma única página na memória compartilhada. O cache predefinido é de acordo com a conexão. Isso pode não ser suficiente para lidar com a workload quando muitas sessões simultâneas estão recebendo um valor de sequência. 

# LWLock:lock\$1manager (LWLock:lockmanager)
<a name="wait-event.lw-lock-manager"></a>

Esse evento ocorre quando o mecanismo do RDS para PostgreSQL mantém a área de memória do bloqueio compartilhado para alocar, conferir e desalocar um bloqueio nos casos em que um bloqueio de caminho rápido não é possível.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.lw-lock-manager.context.supported)
+ [

## Contexto
](#wait-event.lw-lock-manager.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.lw-lock-manager.causes)
+ [

## Ações
](#wait-event.lw-lock-manager.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.lw-lock-manager.context.supported"></a>

As informações de eventos de espera são relevantes para o RDS para PostgreSQL versão 9.6 e posteriores. Para versões do RDS para PostgreSQL anteriores à versão 13, o nome desse evento de espera é `LWLock:lock_manager`. Para o RDS para PostgreSQL versão 13 e posteriores, o nome desse evento de espera é `LWLock:lockmanager`. 

## Contexto
<a name="wait-event.lw-lock-manager.context"></a>

Quando você emite uma instrução SQL, o RDS para PostgreSQL registra bloqueios para proteger a estrutura, os dados e a integridade do banco de dados durante operações simultâneas. O mecanismo pode atingir esse objetivo utilizando um bloqueio de caminho rápido ou um bloqueio de caminho que não é rápido. Um bloqueio de caminho que não é rápido é mais caro e gera mais sobrecarga do que um bloqueio de caminho rápido.

### Bloqueio de caminho rápido
<a name="wait-event.lw-lock-manager.context.fast-path"></a>

Para reduzir a sobrecarga de bloqueios que são retirados e liberados com frequência, mas que raramente entram em conflito, os processos de backend podem utilizar o bloqueio de caminho rápido. O banco de dados usa esse mecanismo para bloqueios que atendem aos seguintes critérios:
+ Usam o método de bloqueio DEFAULT.
+ Representam um bloqueio em uma relação de banco de dados em vez de uma relação compartilhada.
+ São bloqueios fracos que provavelmente não entrarão em conflito.
+ O mecanismo é capaz de verificar rapidamente se nenhum bloqueio conflitante pode existir.

O mecanismo não pode utilizar o bloqueio rápido de caminho quando uma das seguintes condições é verdadeira:
+ O bloqueio não atende aos critérios anteriores.
+ Não há mais slots disponíveis para o processo de backend.

Para ajustar as consultas para bloqueio rápido, é possível usar a consulta a seguir.

```
SELECT count(*), pid, mode, fastpath
  FROM pg_locks
 WHERE fastpath IS NOT NULL
 GROUP BY 4,3,2
 ORDER BY pid, mode;
 count | pid  |      mode       | fastpath
-------+------+-----------------+----------
16 | 9185 | AccessShareLock | t
336 | 9185 | AccessShareLock | f
1 | 9185 | ExclusiveLock   | t
```

A consulta a seguir mostra somente o total em todo o banco de dados.

```
SELECT count(*), mode, fastpath
  FROM pg_locks
 WHERE fastpath IS NOT NULL
 GROUP BY 3,2
 ORDER BY mode,1;
count |      mode       | fastpath
-------+-----------------+----------
16 | AccessShareLock | t
337 | AccessShareLock | f
1 | ExclusiveLock   | t
(3 rows)
```

Para obter mais informações sobre o bloqueio de caminho rápido, consulte o tópico sobre [caminho rápido](https://github.com/postgres/postgres/blob/master/src/backend/storage/lmgr/README#L70-L76), no README do gerenciador de bloqueios do PostgreSQL e[pg-locks](https://www.postgresql.org/docs/9.3/view-pg-locks.html#AEN98195) na documentação do PostgreSQL. 

### Exemplo de um problema de escalabilidade para o gerenciador de bloqueios
<a name="wait-event.lw-lock-manager.context.lock-manager"></a>

Neste exemplo, uma tabela chamada `purchases` armazena cinco anos de dados, particionados por dia. Cada partição possui dois índices. A seguinte sequência de eventos ocorre:

1. Você consulta muitos dias de dados, o que exige que o banco de dados leia várias partições.

1. O banco de dados cria uma entrada de bloqueio para cada partição. Se os índices de partição fizerem parte do caminho de acesso do otimizador, o banco de dados também criará uma entrada de bloqueio para eles.

1. Quando o número de entradas de bloqueios solicitadas para o mesmo processo de backend for maior que 16, que é o valor de `FP_LOCK_SLOTS_PER_BACKEND`, o gerenciador de bloqueio usará o método de bloqueio de caminho não rápido.

Aplicações modernas podem ter centenas de sessões. Se sessões simultâneas estiverem consultando o pai sem a devida limpeza da partição, o banco de dados poderá criar centenas ou até milhares de bloqueios de caminho não rápidos. Em geral, quando essa simultaneidade é maior que o número de vCPUs, o evento de espera `LWLock:lock_manager` é exibido.

**nota**  
O evento de espera `LWLock:lock_manager` não está relacionado ao número de partições ou índices em um esquema de banco de dados e sim ao número de bloqueios de caminho não rápidos que o banco de dados deve controlar.

## Possíveis causas do maior número de esperas
<a name="wait-event.lw-lock-manager.causes"></a>

Quando o evento de espera `LWLock:lock_manager` ocorre mais do que o normal, possivelmente indicando um problema de performance, as causas mais prováveis de picos súbitos são:
+ Sessões ativas simultâneas estão executando consultas que não utilizam bloqueios de caminho rápido. Essas sessões também excedem a vCPU máxima.
+ Um número elevado de sessões ativas simultâneas está acessando uma tabela fortemente particionada. Cada partição possui vários índices.
+ O banco de dados está passando por uma tempestade de conexões. Por padrão, algumas aplicações e softwares de grupo de conexões criam mais conexões quando o banco de dados está lento. Essa prática piora o problema. Ajuste o software do grupo de conexões para que tempestades de conexões não ocorram.
+ Um número elevado de sessões consulta uma tabela pai sem separar partições.
+ Um comando de linguagem de definição de dados (DDL), linguagem de manipulação de dados (DML) ou manutenção bloqueia exclusivamente uma relação ocupada ou tuplas que são frequentemente acessadas ou modificadas.

## Ações
<a name="wait-event.lw-lock-manager.actions"></a>

Se o evento de espera `CPU` ocorrer, isso não indica necessariamente um problema de performance. Responda a esse evento somente quando a performance piorar e esse evento de espera estiver dominando a carga do banco de dados.

**Topics**
+ [

### Usar a limpeza de partição
](#wait-event.lw-lock-manager.actions.pruning)
+ [

### Remover índices desnecessários
](#wait-event.lw-lock-manager.actions.indexes)
+ [

### Ajustar suas consultas para bloqueio de caminho rápido
](#wait-event.lw-lock-manager.actions.tuning)
+ [

### Fazer ajustes com base em eventos de espera
](#wait-event.lw-lock-manager.actions.other-waits)
+ [

### Reduzir gargalos de hardware
](#wait-event.lw-lock-manager.actions.hw-bottlenecks)
+ [

### Usar um agrupador de conexões
](#wait-event.lw-lock-manager.actions.pooler)
+ [

### Fazer upgrade da versão do RDS para PostgreSQL
](#wait-event.lw-lock-manager.actions.pg-version)

### Usar a limpeza de partição
<a name="wait-event.lw-lock-manager.actions.pruning"></a>

*Limpeza de partição* é uma estratégia de otimização de consultas para tabelas declarativamente particionadas que exclui partições desnecessárias das verificações de tabelas, melhorando assim a performance. Por padrão, a remoção de partição está ativada. Se ela estiver desativada, ative-a da seguinte maneira.

```
SET enable_partition_pruning = on;
```

As consultas podem tirar proveito da limpeza de partição quando suas cláusula `WHERE` contêm a coluna utilizada para o particionamento. Para obter mais informações, consulte o tópico sobre [Limpeza de partição](https://www.postgresql.org/docs/current/ddl-partitioning.html#DDL-PARTITION-PRUNING), na documentação do PostgreSQL.

### Remover índices desnecessários
<a name="wait-event.lw-lock-manager.actions.indexes"></a>

Seu banco de dados pode conter índices não utilizados ou raramente utilizados. Se esse for o caso, considere excluí-los. Realize um dos procedimentos a seguir:
+ Saiba mais sobre como encontrar índices desnecessários lendo o tópico sobre [Índices não utilizados](https://wiki.postgresql.org/wiki/Index_Maintenance#Unused_Indexes) na wiki do PostgreSQL.
+ Execute o PG Collector. Esse script SQL reúne informações do banco de dados e as apresenta em um relatório HTML consolidado. Confira a seção “Índices não utilizados”. Para obter mais informações, consulte [pg-collector](https://github.com/awslabs/pg-collector) no Repositório AWS Labs GitHub.

### Ajustar suas consultas para bloqueio de caminho rápido
<a name="wait-event.lw-lock-manager.actions.tuning"></a>

Para descobrir se as suas consultas usam o bloqueio de caminho rápido, consulte a coluna `fastpath` na tabela `pg_locks`. Se as suas consultas não estiverem utilizando o bloqueio de caminho rápido, tente reduzir o número de relações por consulta para menos de 16.

### Fazer ajustes com base em eventos de espera
<a name="wait-event.lw-lock-manager.actions.other-waits"></a>

Se `LWLock:lock_manager` for o primeiro ou o segundo na lista de principais esperas, verifique se os seguintes eventos de espera também aparecem na lista:
+ `Lock:Relation`
+ `Lock:transactionid`
+ `Lock:tuple`

Se os eventos anteriores aparecerem em posição elevada na lista, considere ajustar esses eventos de espera primeiro. Esses eventos podem ser um fator impulsionador para `LWLock:lock_manager`.

### Reduzir gargalos de hardware
<a name="wait-event.lw-lock-manager.actions.hw-bottlenecks"></a>

É possível que haja um gargalo de hardware, como falta de CPU ou uso máximo da largura de banda do Amazon EBS. Nesses casos, considere reduzir gargalos de hardware. Considere as ações a seguir:
+ Aumente a escala da sua classe de instância na vertical.
+ Otimize consultas que consomem grandes quantidades de CPU e memória.
+ Altere a lógica da aplicação.
+ Arquive os dados.

Para obter mais informações sobre CPU, memória e largura de banda da rede do EBS, consulte [Tipos de instâncias do Amazon RDS](https://aws.amazon.com/rds/instance-types/).

### Usar um agrupador de conexões
<a name="wait-event.lw-lock-manager.actions.pooler"></a>

Se o número total de conexões ativas exceder o máximo de vCPU, mais processos do SO exigirão CPU do que o tipo de instância pode suportar. Nesse caso, considere utilizar ou ajustar um grupo de conexões. Para obter mais informações sobre as vCPUs para o seu tipo de instância, consulte o tópico sobre [Tipos de instância do Amazon RDS](https://aws.amazon.com/rds/instance-types/).

Para obter mais informações sobre agrupamento de conexões, consulte os seguintes recursos:
+ [Amazon RDS Proxy](rds-proxy.md)
+ [pgbouncer](http://www.pgbouncer.org/usage.html)
+ [Grupos conexões e fontes de dados](https://www.postgresql.org/docs/7.4/jdbc-datasource.html), na *Documentação do PostgreSQL*

### Fazer upgrade da versão do RDS para PostgreSQL
<a name="wait-event.lw-lock-manager.actions.pg-version"></a>

Se a versão atual do RDS para PostgreSQL for menor que 12, atualize para a versão 12 ou posterior. As versões 12 e posteriores do PostgreSQL têm um mecanismo de partição aprimorado. Para obter mais informações sobre a versão 12, consulte [Notas de release do PostgreSQL 12.0]( https://www.postgresql.org/docs/release/12.0/). Para obter mais informações sobre atualização do RDS para PostgreSQL, consulte [Atualizações do mecanismo de banco de dados do RDS para PostgreSQL](USER_UpgradeDBInstance.PostgreSQL.md).

# LWLock:pg\$1stat\$1statements
<a name="apg-rpg-lwlockpgstat"></a>

O evento de espera LWLock:pg\$1stat\$1statements ocorre quando a extensão `pg_stat_statements` obtém um bloqueio exclusivo na tabela de hash que rastreia instruções SQL. Isso acontece nos seguintes cenários:
+ Quando o número de instruções rastreadas atinge o valor configurado do parâmetro `pg_stat_statements.max` e é necessário abrir espaço para mais entradas, a extensão executa uma classificação no número de chamadas, remove 5% das instruções menos executadas e preenche novamente o hash com as entradas restantes.
+ Quando `pg_stat_statements` executa uma operação `garbage collection` no arquivo `pgss_query_texts.stat` no disco e reescreve o arquivo.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#apg-rpg-lwlockpgstat.supported)
+ [

## Contexto
](#apg-rpg-lwlockpgstat.context)
+ [

## Possíveis causas do maior número de esperas
](#apg-rpg-lwlockpgstat.causes)
+ [

## Ações
](#apg-rpg-lwlockpgstat.actions)

## Versões compatíveis do mecanismo
<a name="apg-rpg-lwlockpgstat.supported"></a>

 As informações sobre esse evento de espera são aceitas em todas as versões do RDS para PostgreSQL. 

## Contexto
<a name="apg-rpg-lwlockpgstat.context"></a>

**Conceitos básicos sobre a extensão pg\$1stat\$1statements**: essa extensão rastreia as estatísticas de execução de instruções SQL em uma tabela de hash. Ela rastreia as instruções SQL até o limite definido pelo parâmetro `pg_stat_statements.max`. Esse parâmetro determina o número máximo de instruções que podem ser rastreadas, o qual corresponde ao número máximo de linhas na visualização pg\$1stat\$1statements.

**Persistência das estatísticas de instrução**: a extensão mantém as estatísticas da instrução em todas as reinicializações da instância:
+ Gravando dados em um arquivo chamado pg\$1stat\$1statements.stat.
+ Usando o parâmetro pg\$1stat\$1statements.save para controlar o comportamento de persistência.

Quando pg\$1stat\$1statements.save é definido como:
+ ativado (padrão): as estatísticas são salvas no desligamento e recarregadas na inicialização do servidor.
+ desativado: as estatísticas não são salvas no desligamento nem recarregadas na inicialização do servidor.

**Armazenamento de texto de consulta**: a extensão armazena o texto das consultas rastreadas em um arquivo chamado `pgss_query_texts.stat`. Esse arquivo pode aumentar até o dobro do tamanho médio de todas as instruções SQL rastreadas antes que a coleta de resíduos ocorra. A extensão requer um bloqueio exclusivo na tabela de hash durante as operações de limpeza e regravação do arquivo `pgss_query_texts.stat`.

**Processo de desalocação de instruções**: quando o número de instruções rastreadas atinge o limite `pg_stat_statements.max` e novas instruções precisam ser rastreadas, a extensão:
+ Obtém um bloqueio exclusivo (LWLock:pg\$1stat\$1statements) na tabela de hash.
+ Carrega os dados existentes na memória local.
+ Executa uma classificação rápida com base no número de chamadas.
+ Remove as instruções menos chamadas (5% inferiores).
+ Preenche novamente a tabela de hash com as entradas restantes.

**Monitoramento da desalocação de instruções**: no PostgreSQL 14 e versões posteriores, você pode monitorar a desalocação de instruções usando a visualização pg\$1stat\$1statements\$1info. Essa visualização inclui uma coluna de desalocação que mostra quantas vezes as instruções foram desalocadas para abrir espaço para novas.

Se a desalocação de instruções ocorrer com frequência, haverá uma coleta de resíduos mais frequente do arquivo `pgss_query_texts.stat` no disco.

## Possíveis causas do maior número de esperas
<a name="apg-rpg-lwlockpgstat.causes"></a>

As causas típicas do aumento de esperas `LWLock:pg_stat_statements` incluem:
+ Um aumento no número de consultas exclusivas usadas pela aplicação.
+ O valor do parâmetro `pg_stat_statements.max` é pequeno em comparação ao número de consultas exclusivas que estão sendo usadas.

## Ações
<a name="apg-rpg-lwlockpgstat.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera. Você pode identificar eventos `LWLock:pg_stat_statements` utilizando o Insights de Performance do Amazon RDS ou consultando a visualização `pg_stat_activity`.

Ajuste os parâmetros `pg_stat_statements` a seguir para controlar o comportamento de rastreamento e reduzir os eventos de espera das instruções LWLock:pg\$1stat\$1.

**Topics**
+ [

### Desabilitar o parâmetro pg\$1stat\$1statements.track
](#apg-rpg-lwlockpgstat.actions.disabletrack)
+ [

### Aumentar o parâmetro pg\$1stat\$1statements.max
](#apg-rpg-lwlockpgstat.actions.increasemax)
+ [

### Desabilitar o parâmetro pg\$1stat\$1statements.track\$1utility
](#apg-rpg-lwlockpgstat.actions.disableutility)

### Desabilitar o parâmetro pg\$1stat\$1statements.track
<a name="apg-rpg-lwlockpgstat.actions.disabletrack"></a>

Se o evento de espera LWLock:pg\$1stat\$1statements estiver afetando negativamente o desempenho do banco de dados e for necessária uma solução rápida antes de uma análise mais aprofundada da visualização `pg_stat_statements` para identificar a causa-raiz, o parâmetro `pg_stat_statements.track` poderá ser desabilitado configurando-o como `none`. Isso desabilitará a coleta de estatísticas de instrução.

### Aumentar o parâmetro pg\$1stat\$1statements.max
<a name="apg-rpg-lwlockpgstat.actions.increasemax"></a>

Para reduzir a desalocação e minimizar a coleta de resíduos do arquivo `pgss_query_texts.stat` no disco, aumente o valor do parâmetro `pg_stat_statements.max`. O valor padrão é `5,000`.

**nota**  
O parâmetro `pg_stat_statements.max` é estático. É necessário reinicializar a instância de banco de dados para aplicar qualquer alteração nesse parâmetro. 

### Desabilitar o parâmetro pg\$1stat\$1statements.track\$1utility
<a name="apg-rpg-lwlockpgstat.actions.disableutility"></a>

Você pode analisar a visualização pg\$1stat\$1statements para determinar quais comandos do utilitário estão consumindo mais recursos rastreados por `pg_stat_statements`.

O parâmetro `pg_stat_statements.track_utility` controla se o módulo rastreia os comandos do utilitário, que incluem todos os comandos, exceto SELECT, INSERT, UPDATE, DELETE e MERGE. Esse parâmetro é definido como por padrão `on`.

Por exemplo, quando sua aplicação usa muitas consultas de ponto de salvamento, que são inerentemente exclusivas, ela pode aumentar a desalocação de instruções. Para resolver isso, você pode desabilitar o parâmetro `pg_stat_statements.track_utility` para impedir que `pg_stat_statements` rastreie consultas de pontos de salvamento.

**nota**  
O parâmetro `pg_stat_statements.track_utility` é dinâmico. Você pode alterar o respectivo valor sem reiniciar a instância de banco de dados.

**Example Exemplo de consultas exclusivas de ponto de salvamento em pg\$1stat\$1statements**  <a name="savepoint-queries"></a>

```
                     query                       |       queryid       
-------------------------------------------------+---------------------
 SAVEPOINT JDBC_SAVEPOINT_495701                 | -7249565344517699703
 SAVEPOINT JDBC_SAVEPOINT_1320                   | -1572997038849006629
 SAVEPOINT JDBC_SAVEPOINT_26739                  |  54791337410474486
 SAVEPOINT JDBC_SAVEPOINT_1294466                |  8170064357463507593
 ROLLBACK TO SAVEPOINT JDBC_SAVEPOINT_65016      | -33608214779996400
 SAVEPOINT JDBC_SAVEPOINT_14185                  | -2175035613806809562
 SAVEPOINT JDBC_SAVEPOINT_45837                  | -6201592986750645383
 SAVEPOINT JDBC_SAVEPOINT_1324                   |  6388797791882029332
```

O PostgreSQL 17 inclui vários aprimoramentos para o rastreamento de comandos de utilitário:
+ Os nomes de ponto de salvamento agora são exibidos como constantes.
+ Os IDs de transação global (GIDs) dos comandos de confirmação em duas fases agora são exibidos como constantes.
+ Os nomes das instruções DEALLOCATE são mostrados como constantes.
+ Os parâmetros CALL agora são exibidos como constantes.

# LWLock:SubtransSLRU (LWLock:SubtransControlLock)
<a name="wait-event.lwlocksubtransslru"></a>

Os eventos de espera `LWLock:SubtransSLRU` e `LWLock:SubtransBuffer` indicam que uma sessão está aguardando para acessar o cache simples utilizado com menor frequência (SLRU) para informações de subtransação. Isso ocorre ao determinar a visibilidade da transação e os relacionamentos pai-filho.
+ `LWLock:SubtransSLRU`: um processo está aguardando para acessar o cache simples menos utilizado recentemente (SLRU) para uma subtransação. No RDS para PostgreSQL antes da versão 13, esse evento de espera é chamado de `SubtransControlLock`.
+ `LWLock:SubtransBuffer`: um processo está aguardando a E/S em um buffer simples menos utilizado recentemente (SLRU) para uma subtransação. No RDS para PostgreSQL antes da versão 13, esse evento de espera é chamado de `subtrans`.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.lwlocksubtransslru.supported)
+ [

## Contexto
](#wait-event.lwlocksubtransslru.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.lwlocksubtransslru.causes)
+ [

## Ações
](#wait-event.lwlocksubtransslru.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.lwlocksubtransslru.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.lwlocksubtransslru.context"></a>

**Noções básicas sobre subtransações**: subtransação é uma transação dentro de uma transação no PostgreSQL. Também é conhecida como transação aninhada.

Normalmente, as subtransações são criadas quando você usa:
+ `SAVEPOINT`Comandos da 
+ Blocos de exceção (`BEGIN/EXCEPTION/END`)

As subtransações permitem reverter partes de uma transação sem afetar toda ela. Isso oferece controle refinado sobre o gerenciamento de transações.

**Detalhes da implementação**: o PostgreSQL implementa subtransações como estruturas aninhadas nas transações principais. Cada subtransação recebe seu próprio ID.

Principais aspectos de implementação:
+ Os IDs de transação são monitorados em `pg_xact`.
+ Os relacionamentos pai-filho são armazenados no subdiretório `pg_subtrans` em `PGDATA`.
+ Cada sessão do banco de dados pode manter até `64` subtransações ativas.
+ Exceder esse limite causa estouro de subtransação, o que requer acesso ao cache simples utilizado com menor frequência (SLRU) para informações de subtransação.

## Possíveis causas do maior número de esperas
<a name="wait-event.lwlocksubtransslru.causes"></a>

As causas comuns de contenção de SLRU por subtransação são as seguintes:
+ **Uso excessivo do tratamento de SAVEPOINT e EXCEPTION**: os procedimentos PL/pgSQL com manipuladores `EXCEPTION` criam automaticamente pontos de salvamento implícitos, independentemente da ocorrência de exceções. Cada `SAVEPOINT` inicia uma nova subtransação. Quando uma única transação acumula mais de 64 subtransações, ela aciona um estouro de SLRU de subtransação.
+ **Configurações de driver e ORM**: o uso de `SAVEPOINT` pode ser explícito no código da aplicação ou implícito nas configurações do driver. Muitas ferramentas de ORM e frameworks de aplicações geralmente usadas comportam transações aninhadas de forma nativa. Veja aqui alguns exemplos comuns:
  + O parâmetro do driver JDBC `autosave`, se definido como `always` ou `conservative`, gera pontos de salvamento antes de cada consulta.
  + Definições de transação do Spring Framework quando configuradas como `propagation_nested`.
  + Trilhos quando `requires_new: true` está definido.
  + SQLAlchemy quando `session.begin_nested` é usado.
  + Django quando blocos `atomic()` aninhados são usados.
  + GORM quando `Savepoint` é usado.
  + psqlODBC quando a configuração do nível de reversão é definida como reversão em nível de instrução (por exemplo, `PROTOCOL=7.4-2`).
+ **Altas workloads simultâneas com transações e subtransações de longa execução**: quando ocorre um estouro de SLRU de subtransação durante workloads altamente simultâneas e transações e subtransações de longa execução, o PostgreSQL sofre uma maior contenção. Isso se manifesta como eventos de espera elevados para bloqueios `LWLock:SubtransBuffer` e `LWLock:SubtransSLRU`.

## Ações
<a name="wait-event.lwlocksubtransslru.actions"></a>

Recomenda-se ações distintas, dependendo dos motivos do evento de espera. Algumas ações fornecem alívio imediato, enquanto outras exigem investigação e correção no longo prazo.

**Topics**
+ [

### Monitorar o uso de subtransações
](#wait-event.lwlocksubtransslru.actions.monitor)
+ [

### Configurar parâmetros de memória
](#wait-event.lwlocksubtransslru.actions.memory)
+ [

### Ações de longo prazo
](#wait-event.lwlocksubtransslru.actions.longterm)

### Monitorar o uso de subtransações
<a name="wait-event.lwlocksubtransslru.actions.monitor"></a>

Para as versões 16.1 e posteriores do PostgreSQL, use a consulta a seguir para monitorar as contagens de subtransações e o status de estouro por backend. Essa consulta une estatísticas de backend com informações de atividades para mostrar quais processos estão usando subtransações:

```
SELECT a.pid, usename, query, state, wait_event_type,
       wait_event, subxact_count, subxact_overflowed
FROM (SELECT id, pg_stat_get_backend_pid(id) pid, subxact_count, subxact_overflowed
      FROM pg_stat_get_backend_idset() id
           JOIN LATERAL pg_stat_get_backend_subxact(id) AS s ON true
     ) a
JOIN pg_stat_activity b ON a.pid = b.pid;
```

Para as versões 13.3 e posteriores do PostgreSQL, monitore a visualização `pg_stat_slru` da pressão do cache de subtransação. A consulta SQL a seguir recupera estatísticas de cache SLRU para o componente Subtrans:

```
SELECT * FROM pg_stat_slru WHERE name = 'Subtrans';
```

Um valor `blks_read` consistentemente crescente indica acesso frequente ao disco para subtransações não armazenadas em cache, sinalizando uma possível pressão no cache de SLRU.

### Configurar parâmetros de memória
<a name="wait-event.lwlocksubtransslru.actions.memory"></a>

Para o PostgreSQL 17.1 e versões posteriores, é possível configurar o tamanho do cache de SLRU de subtransações usando o parâmetro `subtransaction_buffers`. O seguinte exemplo de configuração mostra como definir o parâmetro de buffer de subtransações:

```
subtransaction_buffers = 128
```

Esse parâmetro especifica a quantidade de memória compartilhada utilizada para armazenar conteúdo de subtransação (`pg_subtrans`). Quando especificado sem unidades, o valor representa blocos de `BLCKSZ` bytes, normalmente 8 KB cada. Por exemplo, definir o valor como 128 aloca 1 MB (128 x 8 kB) de memória para o cache de subtransações.

**nota**  
É possível definir esse parâmetro em nível de cluster para que todas as instâncias permaneçam consistentes. Teste e ajuste o valor para melhor atender aos requisitos específicos da workload e à classe de instância. É necessário reinicializar a instância do gravador para que a alteração do parâmetro tenha efeito.

### Ações de longo prazo
<a name="wait-event.lwlocksubtransslru.actions.longterm"></a>
+ **Examinar o código e as configurações da aplicação**: analise as configurações do código da aplicação e do driver do banco de dados quanto ao uso explícito e implícito de `SAVEPOINT` e ao uso de subtransações em geral. Identifique transações que podem geram mais de 64 subtransações.
+ **Reduzir o uso de pontos de salvamento**: minimize o uso de pontos de salvamento nas transações:
  + Analise os procedimentos PL/pgSQL e funções com blocos EXCEPTION. Os blocos EXCEPTION criam automaticamente pontos de salvamento implícitos, que podem contribuir para o estouro de subtransações. Cada cláusula EXCEPTION cria uma subtransação, independentemente de uma exceção realmente ocorrer durante a execução.  
**Example**  

    Exemplo 1: uso problemático do bloco EXCEPTION

    O exemplo de código a seguir mostra o uso problemático do bloco EXCEPTION que cria várias subtransações:

    ```
    CREATE OR REPLACE FUNCTION process_user_data()
    RETURNS void AS $$
    DECLARE
        user_record RECORD;
    BEGIN
        FOR user_record IN SELECT * FROM users LOOP
            BEGIN
                -- This creates a subtransaction for each iteration
                INSERT INTO user_audit (user_id, action, timestamp)
                VALUES (user_record.id, 'processed', NOW());
                
                UPDATE users 
                SET last_processed = NOW() 
                WHERE id = user_record.id;
                
            EXCEPTION
                WHEN unique_violation THEN
                    -- Handle duplicate audit entries
                    UPDATE user_audit 
                    SET timestamp = NOW() 
                    WHERE user_id = user_record.id AND action = 'processed';
            END;
        END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    ```

    O exemplo de código aprimorado a seguir reduz o uso de subtransações usando UPSERT em vez do tratamento de exceções:

    ```
    CREATE OR REPLACE FUNCTION process_user_data()
    RETURNS void AS $$
    DECLARE
        user_record RECORD;
    BEGIN
        FOR user_record IN SELECT * FROM users LOOP
            -- Use UPSERT to avoid exception handling
            INSERT INTO user_audit (user_id, action, timestamp)
            VALUES (user_record.id, 'processed', NOW())
            ON CONFLICT (user_id, action) 
            DO UPDATE SET timestamp = NOW();
            
            UPDATE users 
            SET last_processed = NOW() 
            WHERE id = user_record.id;
        END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    ```  
**Example**  

    Exemplo 2: manipulador de exceções STRICT

    O exemplo de código a seguir mostra o tratamento problemático de EXCEPTION com NO\$1DATA\$1FOUND:

    ```
    CREATE OR REPLACE FUNCTION get_user_email(p_user_id INTEGER)
    RETURNS TEXT AS $$
    DECLARE
        user_email TEXT;
    BEGIN
        BEGIN
            -- STRICT causes an exception if no rows or multiple rows found
            SELECT email INTO STRICT user_email 
            FROM users 
            WHERE id = p_user_id;
            
            RETURN user_email;
            
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN 'Email not found';
        END;
    END;
    $$ LANGUAGE plpgsql;
    ```

    O exemplo de código aprimorado a seguir evita subtransações usando IF NOT FOUND em vez do tratamento de exceções:

    ```
    CREATE OR REPLACE FUNCTION get_user_email(p_user_id INTEGER)
    RETURNS TEXT AS $$
    DECLARE
        user_email TEXT;
    BEGIN
         SELECT email INTO user_email 
         FROM users 
         WHERE id = p_user_id;
            
         IF NOT FOUND THEN
             RETURN 'Email not found';
         ELSE
             RETURN user_email;
         END IF;
    END;
    $$ LANGUAGE plpgsql;
    ```
  + Driver JDBC: o parâmetro `autosave`, se definido como `always` ou `conservative`, gera pontos de salvamento antes de cada consulta. Avalie se a configuração `never` seria aceitável para sua aplicação.
  + Driver ODBC do PostgreSQL (psqlODBC): a configuração em nível de reversão (para reversão em nível da instrução) cria pontos de salvamento implícitos para habilitar a funcionalidade de reversão da instrução. Avalie se a reversão em nível de transação ou nenhuma reversão seria aceitável para sua aplicação. 
  + Examinar as configurações de transações do ORM
  + Pense nas estratégias alternativas de tratamento de erros que não exijam pontos de salvamento
+ **Otimizar o design da transação**: reestruture as transações para evitar o agrupamento excessivo e reduzir a probabilidade de condições de estouro de subtransações.
+ **Reduzir as transações de longa duração**: as transações de longa duração podem agravar os problemas com subtransações ao reter as informações delas por mais tempo. Monitore as métricas do Insights de Performance e configure o parâmetro `idle_in_transaction_session_timeout` para encerrar automaticamente as transações ociosas.
+ Monitorar as métricas do Insights de Performance: acompanhe métricas, incluindo `idle_in_transaction_count` (número de sessões inativas no estado da transação) e `idle_in_transaction_max_time` (duração da transação ociosa mais longa) para detectar transações de longa duração.
+ Configurar `idle_in_transaction_session_timeout`: defina esse parâmetro em seu grupo de parâmetros para encerrar automaticamente transações ociosas após um período especificado.
+ Monitoramento proativo: monitore altas ocorrências de eventos de espera `LWLock:SubtransBuffer` e `LWLock:SubtransSLRU` para detectar contenções relacionadas a subtransações antes que elas se tornem críticas.

# Tempo limite:PgSleep
<a name="wait-event.timeoutpgsleep"></a>

O evento `Timeout:PgSleep` ocorre quando um processo do servidor chama a função `pg_sleep` e está aguardando o tempo limite de suspensão expirar.

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.timeoutpgsleep.context.supported)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.timeoutpgsleep.causes)
+ [

## Ações
](#wait-event.timeoutpgsleep.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.timeoutpgsleep.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Possíveis causas do maior número de esperas
<a name="wait-event.timeoutpgsleep.causes"></a>

Esse evento de espera ocorre quando uma aplicação, uma função armazenada ou um usuário emite uma instrução SQL que chama uma das seguintes funções:
+ `pg_sleep`
+ `pg_sleep_for`
+ `pg_sleep_until`

As funções anteriores atrasarão a execução até que o número especificado de segundos tenha decorrido. Por exemplo, `SELECT pg_sleep(1)` pausa por 1 segundo. Para obter mais informações, consulte [Atrasar a execução](https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-DELAY) na documentação do PostgreSQL.

## Ações
<a name="wait-event.timeoutpgsleep.actions"></a>

Identifique a instrução que estava executando a função `pg_sleep`. Determine se o uso da função é apropriado.

# Timeout:VacuumDelay
<a name="wait-event.timeoutvacuumdelay"></a>

O evento `Timeout:VacuumDelay` indica que o limite de custo para E/S de vácuo foi excedido e que o processo de vácuo foi suspenso. As operações de vácuo são interrompidas pelo período especificado no respectivo parâmetro de atraso de custo e, depois, ele retoma seu trabalho. Para o comando de vácuo manual, o atraso é especificado no parâmetro `vacuum_cost_delay`. Para o daemon de vácuo automático, o atraso é especificado no `autovacuum_vacuum_cost_delay parameter.` 

**Topics**
+ [

## Versões compatíveis do mecanismo
](#wait-event.timeoutvacuumdelay.context.supported)
+ [

## Contexto
](#wait-event.timeoutvacuumdelay.context)
+ [

## Possíveis causas do maior número de esperas
](#wait-event.timeoutvacuumdelay.causes)
+ [

## Ações
](#wait-event.timeoutvacuumdelay.actions)

## Versões compatíveis do mecanismo
<a name="wait-event.timeoutvacuumdelay.context.supported"></a>

Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.

## Contexto
<a name="wait-event.timeoutvacuumdelay.context"></a>

O PostgreSQL tem um daemon de vácuo automático e um comando de vácuo manual. O processo de vácuo automático está “ativado” por padrão para instâncias de banco de dados do RDS para PostgreSQL. O comando de vácuo manual é utilizado conforme a necessidade, por exemplo, para limpar tabelas de tuplas inoperantes ou gerar novas estatísticas.

Quando a aspiração está em andamento, o PostgreSQL usa um contador interno para acompanhar os custos estimados à medida que o sistema executa várias operações de E/S. Quando o contador atinge o valor especificado pelo parâmetro de limite de custo, o processo que executa a operação permanece inativo pelo breve período especificado no parâmetro de atraso de custo. Depois, ele redefine o contador e continua as operações. 

O processo de vácuo tem parâmetros que podem ser usados para regular o consumo de recursos. O vácuo automático e o comando de vácuo manual têm seus próprios parâmetros para definir o valor limite de custo. Eles também têm seus próprios parâmetros para especificar um atraso de custo, uma quantidade de tempo para colocar o vácuo em repouso quando o limite é atingido. Dessa forma, o parâmetro de atraso de custo funciona como um controle de utilização do consumo de recursos. Nas listas a seguir, você pode encontrar a descrição desses parâmetros. 

**Parâmetros que afetam o controle de utilização do daemon de vácuo automático**
+ `[autovacuum\$1vacuum\$1cost\$1limit](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-LIMIT)`: especifica o valor limite de custo a ser utilizado em operações automáticas de vácuo. Aumentar a configuração desse parâmetro permite que o processo de vácuo use mais recursos e diminua o evento de espera `Timeout:VacuumDelay`. 
+ `[autovacuum\$1vacuum\$1cost\$1delay](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)`: especifica o valor de atraso de custo a ser utilizado em operações automáticas de vácuo. O valor padrão é 2 milissegundos. Definir o parâmetro de atraso como 0 desativa o controle de utilização e, portanto, o evento de espera `Timeout:VacuumDelay` não será exibido. 

Para ter mais informações, consulte [Automatic Vacuuming](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY) (Aplicação automática do vacuum) na documentação do PostgreSQL.

**Parâmetros que afetam o controle de utilização do processo de vácuo manual**
+ `vacuum_cost_limit`: o limite no qual o processo de vácuo é suspenso. Por padrão, o limite é 200. Esse número representa as estimativas de custo acumuladas para E/S extras necessárias para vários recursos. Aumentar esse valor reduz o número do evento de espera `Timeout:VacuumDelay`. 
+ `vacuum_cost_delay`: a quantidade de tempo que o processo de vácuo permanece inativo quando o limite de custo do vácuo é atingido. A configuração padrão é 0, o que significa que esse recurso está desativado. Você pode definir isso como um valor inteiro para especificar o número de milissegundos para ativar esse recurso, mas recomendamos que você o deixe na configuração padrão.

Para obter mais informações sobre o parâmetro `vacuum_cost_delay`, consulte [Resource Consumption](https://www.postgresql.org/docs/current/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST) (Consumo de recursos) na documentação do PostgreSQL. 

Para saber mais sobre como configurar e usar o vácuo automático com o RDS for PostgreSQL, consulte [Trabalhar com o autovacuum do PostgreSQL no Amazon RDS para PostgreSQL](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md). 

## Possíveis causas do maior número de esperas
<a name="wait-event.timeoutvacuumdelay.causes"></a>

O `Timeout:VacuumDelay` é afetado pelo equilíbrio entre as configurações dos parâmetros de limite de custo (`vacuum_cost_limit`, `autovacuum_vacuum_cost_limit`) e os parâmetros de atraso de custo (`vacuum_cost_delay`, `autovacuum_vacuum_cost_delay`) que controlam a duração da suspensão do vácuo. Aumentar o valor de um parâmetro de limite de custo permite que mais recursos sejam utilizados pelo vácuo antes de serem colocados em repouso. Isso ocasiona menos eventos de espera `Timeout:VacuumDelay`. O aumento de qual quer um dos parâmetros de atraso faz com que o evento de espera `Timeout:VacuumDelay` ocorra com maior frequência e por longos períodos. 

A configuração do parâmetro `autovacuum_max_workers` também pode aumentar o número de `Timeout:VacuumDelay`. Cada processo adicional de processamento do vácuo automático contribui para o mecanismo interno do contador e, portanto, o limite pode ser atingido mais rapidamente do que com um único processo de vácuo automático. À medida que o limite de custo é atingido mais rapidamente, o atraso de custo é aplicado com maior frequência, ocasionando mais eventos de espera `Timeout:VacuumDelay`. Para obter mais informações, consulte [autovacuum\$1max\$1workers](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-MAX-WORKERS) na documentação do PostgreSQL.

Objetos grandes, como 500 GB ou maiores, também aumentam esse evento de espera porque pode levar algum tempo para que o vácuo conclua o processamento de objetos grandes.

## Ações
<a name="wait-event.timeoutvacuumdelay.actions"></a>

Se as operações de vácuo forem concluídas conforme o esperado, nenhuma correção será necessária. Em outras palavras, esse evento de espera não indica necessariamente um problema. Isso indica que o vácuo está sendo colocado em repouso pelo período especificado no parâmetro de atraso para que os recursos possam ser aplicados a outros processos que precisam ser concluídos. 

Se quiser que as operações de vácuo sejam concluídas mais rapidamente, você poderá reduzir os parâmetros de atraso. Isso reduz o tempo em que o vácuo permanece suspenso. 