Tuning PostgreSQL não é copiar uma lista de parâmetros para o postgresql.conf. É um processo de engenharia: medir o workload, localizar o recurso limitante, formular uma hipótese, mudar o mínimo necessário e provar o resultado. Uma configuração excelente para um ERP transacional pode derrubar um ambiente analítico; um índice que acelera leitura pode aumentar WAL, espaço e custo de escrita. Este guia apresenta um método seguro para ambientes de produção e para equipes que procuram tuning PostgreSQL no Brasil.
Resposta rápida: comece por queries e waits, não por parâmetros. Registre latência, throughput, CPU, I/O, conexões, arquivos temporários, WAL e comportamento do autovacuum. Só então ajuste a camada que as evidências apontarem.
O que um tuning PostgreSQL completo precisa avaliar
Performance é o resultado da interação entre aplicação, modelo de dados, planner, configuração, sistema operacional e armazenamento. Por isso, um diagnóstico útil separa cinco camadas:
- Workload: volume, concorrência, proporção de leitura e escrita, picos, jobs, relatórios e sazonalidade.
- Queries e planos: consultas de maior impacto, estimativas erradas, scans, joins, sorts, funções e regressões de plano.
- Estrutura: índices, tipos, particionamento, bloat, estatísticas e distribuição dos dados.
- Configuração: memória, conexões, WAL, checkpoints, autovacuum, paralelismo e parâmetros do planner.
- Infraestrutura: CPU, RAM, latência de disco, IOPS, filesystem, rede, virtualização e limites de container ou cloud.
Ajustar apenas uma dessas camadas costuma deslocar o gargalo. Aumentar work_mem, por exemplo, pode remover um sort em disco e ao mesmo tempo provocar OOM quando dezenas de operações concorrentes usam o novo limite.
1. Crie uma linha de base antes de alterar parâmetros
Sem baseline, uma mudança que apenas coincidiu com a queda de carga parece melhoria. Registre pelo menos um período normal e um período problemático. Compare percentis de latência, transações por segundo, consumo de CPU, leituras físicas, arquivos temporários, checkpoints, locks e sessões ativas.
SELECT now(), datname,
xact_commit, xact_rollback,
blks_read, blks_hit,
temp_files, temp_bytes,
deadlocks
FROM pg_stat_database
WHERE datname = current_database();
SELECT wait_event_type, wait_event, count(*) AS sessions
FROM pg_stat_activity
WHERE state = 'active'
GROUP BY 1, 2
ORDER BY sessions DESC;
Uma fotografia isolada ajuda pouco. Use deltas ao longo do tempo e relacione-os com deploys, rotinas de batch, crescimento de dados e mudanças de infraestrutura. O objetivo é responder: o banco está limitado por CPU, leitura, escrita, lock, memória, conexão, WAL ou uma consulta específica?
2. Encontre as queries que realmente consomem o ambiente
Otimizar a consulta mais lenta nem sempre gera o maior retorno. Uma query de cinco segundos executada duas vezes por dia pode custar menos que uma de 80 ms executada milhares de vezes por minuto. Com pg_stat_statements, priorize tempo total, média, chamadas e blocos lidos:
SELECT queryid, calls,
round(total_exec_time::numeric, 2) AS total_ms,
round(mean_exec_time::numeric, 2) AS mean_ms,
shared_blks_read, temp_blks_written,
left(query, 180) AS sample
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 20;
Depois capture EXPLAIN (ANALYZE, BUFFERS, WAL) em ambiente seguro. Compare linhas estimadas e reais, buffers lidos, loops, sorts em disco e volume de WAL. Nunca execute ANALYZE sem avaliar o impacto: ele roda a consulta de verdade, inclusive escritas.
Veja também o guia de queries e EXPLAIN e use o analisador de EXPLAIN para uma primeira leitura do plano.
3. Dimensione memória pela concorrência real
Os parâmetros de memória têm naturezas diferentes. shared_buffers reserva memória compartilhada para páginas; effective_cache_size é apenas uma estimativa para o planner; work_mem é um limite por operação de sort ou hash; maintenance_work_mem atende operações de manutenção. Somá-los como se todos fossem reservas fixas produz um orçamento incorreto.
shared_buffers
Em servidor dedicado, 25% da RAM é um ponto inicial comum. Não é uma meta automática: PostgreSQL depende do page cache do sistema operacional, e containers precisam respeitar o limite do cgroup, não a memória total do host.
work_mem
O erro clássico é dividir RAM por max_connections. Uma única query pode ter vários sorts e hashes, além de workers paralelos. Modele operações pesadas simultâneas:
orçamento de work_mem = RAM disponível para operações
consumo potencial = work_mem × operações por query × queries concorrentes × workers
Prefira elevar work_mem por role, banco ou sessão para workloads específicos antes de aumentar globalmente. Confirme o benefício observando temp_blks_written e o método de sort no plano.
Nosso PostgreSQL Configuration Planner ajuda a modelar memória, concorrência, WAL e I/O sem tratar conexões como se fossem operações simultâneas.
4. Controle WAL e checkpoints sem esconder o problema
Checkpoints muito frequentes concentram escrita e podem elevar a latência. Checkpoints longos demais ampliam o volume de WAL necessário para recuperação e exigem capacidade de disco. Avalie max_wal_size, checkpoint_timeout e checkpoint_completion_target em conjunto com taxa de geração de WAL, tempo de recuperação e espaço disponível.
-- PostgreSQL 16 e anteriores
SELECT checkpoints_timed, checkpoints_req,
checkpoint_write_time, checkpoint_sync_time,
buffers_checkpoint, buffers_backend
FROM pg_stat_bgwriter;
-- PostgreSQL 17+
SELECT num_timed, num_requested, write_time, sync_time,
buffers_written
FROM pg_stat_checkpointer;
Um número alto de checkpoints solicitados sugere pressão de WAL, mas aumentar max_wal_size sem investigar escrita, slots e retenção pode apenas adiar o alerta de disco. Em PostgreSQL 17+, métricas de checkpoint foram separadas em pg_stat_checkpointer; sempre confira a documentação da versão em uso.
5. Ajuste o planner ao armazenamento real
random_page_cost e effective_io_concurrency influenciam a escolha entre scans e estratégias de I/O. Copiar valores de NVMe para storage de rede, ou de um servidor dedicado para um volume cloud limitado por IOPS, faz o planner comparar custos irreais.
Antes de mexer nesses parâmetros, valide estatísticas, cardinalidade e correlação das colunas. Muitas decisões ruins do planner vêm de estimativas ruins, não do custo padrão. Use CREATE STATISTICS quando colunas correlacionadas confundem estimativas e mantenha ANALYZE saudável.
6. Trate índices como investimento com custo de escrita
Um bom índice reduz o conjunto de páginas visitadas e pode fornecer a ordenação desejada. Um índice ruim ocupa cache, aumenta WAL e torna INSERT, UPDATE, vacuum e backup mais caros. Para cada candidato, documente:
- a query e o plano que justificam o índice;
- seletividade e ordem das colunas;
- volume de escrita e tamanho esperado;
- sobreposição com índices existentes;
- forma de criação e rollback em produção.
Em tabelas grandes e ativas, CREATE INDEX CONCURRENTLY evita bloquear escritas, mas leva mais tempo, usa mais recursos e pode deixar um índice inválido se falhar. Monitore a operação e valide o plano depois. Consulte o guia de B-tree, GIN e BRIN.
7. Faça o autovacuum acompanhar cada tabela
O autovacuum global atende mal tabelas com tamanhos e taxas de escrita muito diferentes. Em tabelas grandes, um scale_factor aparentemente pequeno ainda pode permitir milhões de dead tuples. Prefira overrides por tabela baseados em volume de atualização, dead ratio, duração do vacuum e risco de wraparound.
SELECT relname, n_live_tup, n_dead_tup,
last_autovacuum, autovacuum_count,
n_tup_upd, n_tup_del
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;
Antes de aumentar agressividade, procure transações longas, sessões idle in transaction e replication slots segurando o horizonte de remoção. Leia o guia completo de tuning de autovacuum.
8. Controle conexões e contenção
max_connections não é uma meta de capacidade. Cada backend consome memória e participa de contenção interna; centenas de conexões ociosas também aumentam o custo operacional. Meça conexões ativas, tempo de espera por pool e simultaneidade real. Para aplicações com muitas conexões curtas, PgBouncer em transaction pooling costuma ser mais seguro do que elevar indefinidamente o limite.
Antes de adotar transaction pooling, valide recursos dependentes de sessão, prepared statements, tabelas temporárias, advisory locks e configuração da aplicação. Pooling resolve custo de conexão; não corrige queries lentas nem transações longas.
9. Tuning PostgreSQL no RDS e Aurora
Em Amazon RDS e Aurora PostgreSQL, o método permanece o mesmo, mas a fronteira de controle muda. Parâmetros vivem em parameter groups, storage pode ter baseline e burst de IOPS, e parte da telemetria vem de CloudWatch e Performance Insights. Relacione métricas da AWS com pg_stat_statements, waits, planos, autovacuum e WAL dentro do banco.
Não conclua que CPU alta exige uma instância maior antes de identificar a query, o plano ou o job que elevou a carga. Da mesma forma, não reduza a instância só por baixa CPU sem validar memória, conexões, I/O, replicação e janela de manutenção.
10. Aplique mudanças com hipótese, validação e rollback
Um ciclo seguro de tuning usa mudanças pequenas e observáveis:
- Defina o sintoma: métrica, janela, impacto e frequência.
- Registre a baseline: percentis, throughput, recursos, plano e configuração atual.
- Declare a hipótese: por que a mudança deve afetar o sintoma.
- Teste: restaure uma carga representativa ou faça rollout controlado.
- Mude uma variável por vez: preserve a capacidade de atribuir causa.
- Valide: compare a mesma janela e procure efeitos colaterais.
- Reverta: execute o rollback se o critério de sucesso não for atingido.
Evite tuning por porcentagem genérica. Recomendações como “sempre use 25%” são pontos de partida, não decisões de produção. Versão, workload, concorrência, container, storage, RPO e comportamento da aplicação precisam entrar no cálculo.
Checklist de tuning PostgreSQL para produção
- Ativar e dimensionar corretamente
pg_stat_statements. - Capturar baseline durante carga normal e durante o problema.
- Priorizar queries por impacto total, não apenas pela maior duração.
- Comparar linhas estimadas e reais com
EXPLAIN. - Modelar
work_mempor operações e concorrência. - Correlacionar checkpoints, WAL, slots e capacidade de disco.
- Revisar índices redundantes, ausentes e caros para escrita.
- Ajustar autovacuum por tabela e remover bloqueadores de xmin.
- Usar pool de conexões quando o padrão da aplicação justificar.
- Documentar hipótese, janela, métrica de sucesso e rollback.
Consultoria de tuning PostgreSQL no Brasil
Quando o ambiente já está afetando clientes, uma análise precisa conectar evidências sem testar no escuro. A PG Monitoring atende empresas remotamente em todo o Brasil com diagnóstico de queries, planos, índices, configuração, autovacuum, WAL, RDS, Aurora e capacidade. O trabalho começa com coleta controlada e preferência por leitura; mudanças são propostas com impacto esperado, risco, validação e rollback.
O conteúdo foi preparado por João Victor Oliveira, Senior Database Administrator com mais de 13 anos de experiência em ambientes críticos de instituições financeiras, setor público, cloud e empresas. Para avaliar um caso real, conheça nossa consultoria de tuning PostgreSQL no Brasil ou solicite um Raio-X PostgreSQL.