PostgreSQL 16: Novidades e melhorias de performance

Descubra os recursos mais importantes da versão 16 do PostgreSQL.

PostgreSQL 16: A versão mais rápida até agora

Lançado em setembro de 2023, o PostgreSQL 16 trouxe melhorias significativas em performance, replicação lógica, monitoramento e segurança. Vamos explorar as mudanças mais impactantes para aplicações em produção.

1. Performance massivamente melhorada

Paralelização de queries mais inteligente

O PostgreSQL 16 executa queries complexas até 3x mais rápido graças a melhorias no query planner:

-- Exemplo: Agregações paralelas
SELECT 
  customer_id,
  COUNT(*),
  SUM(amount)
FROM orders
WHERE created_at > '2025-01-01'
GROUP BY customer_id
HAVING COUNT(*) > 10;

-- PG 15: ~450ms com 4 workers
-- PG 16: ~150ms com paralelização otimizada ✅

FULL/RIGHT JOIN agora paralelo

-- Antes (PG 15): Não paralelizava
SELECT *
FROM large_table_a a
FULL JOIN large_table_b b ON a.id = b.id;

-- PG 16: Usa múltiplos cores automaticamente
-- Speedup: até 5x em tabelas grandes

Incremento de sequences otimizado

-- Contention reduzida em sequences
-- PG 15: Bloqueios frequentes em INSERTs massivos
-- PG 16: 30% mais throughput em INSERTs concorrentes

INSERT INTO events (name, data) 
VALUES ('event', '{"key": "value"}');
-- Agora muito mais rápido com milhares de INSERTs/s

2. Replicação lógica - Muito mais poderosa

Replicar de standby (replica de replica)

-- Agora possível: Master → Replica1 → Replica2
-- PG 15: Só replicava do master
-- PG 16: Replicas podem ser source de outras replicas

-- Na Replica1, crie publicação
CREATE PUBLICATION from_replica FOR ALL TABLES;

-- Na Replica2, crie subscrição da Replica1
CREATE SUBSCRIPTION from_other_replica
CONNECTION 'host=replica1.com ...'
PUBLICATION from_replica;

Replicação de sequences

-- Antes: Sequences não replicavam logicamente
-- PG 16: Sequences inclusos automaticamente!

CREATE PUBLICATION my_pub FOR ALL TABLES WITH (publish_sequences = true);

-- Não precisa mais sincronizar sequences manualmente 🎉

Filtros de replicação por linha

-- Replique apenas linhas específicas
CREATE PUBLICATION active_users_only
FOR TABLE users 
WHERE (status = 'active');

-- Replica apenas clientes premium
CREATE PUBLICATION premium_only
FOR TABLE customers
WHERE (plan = 'premium' OR plan = 'enterprise');

3. Monitoramento e observabilidade

pg_stat_io - Nova view de I/O

-- Detalhe completo de I/O por operação
SELECT 
  backend_type,
  object,
  context,
  reads,
  writes,
  extends,
  op_bytes
FROM pg_stat_io
ORDER BY reads DESC;

-- Exemplo de output:
-- backend_type | object  | reads    | writes
-- client       | relation| 12500000 | 3200000
-- walwriter    | wal     | 0        | 890000

Auto-explain melhorado

-- Configure para logar queries lentas automaticamente
LOAD 'auto_explain';
SET auto_explain.log_min_duration = '100ms';  -- Queries > 100ms
SET auto_explain.log_analyze = true;
SET auto_explain.log_buffers = true;
SET auto_explain.log_timing = true;

-- Agora inclui:
-- ✅ I/O timing detalhado
-- ✅ Buffer usage preciso
-- ✅ WAL usage (novo no PG 16!)

Estatísticas de WAL

-- Nova coluna: WAL usage por query
SELECT 
  query,
  calls,
  wal_records,  -- Novo!
  wal_fpi,      -- Novo!
  wal_bytes     -- Novo!
FROM pg_stat_statements
WHERE wal_bytes > 1000000  -- Queries que geram muito WAL
ORDER BY wal_bytes DESC
LIMIT 10;

4. JSON e tipos de dados

JSON_TABLE - SQL/JSON padrão

-- Extraia JSON para tabela relacional
SELECT * FROM JSON_TABLE(
  '[
    {"id": 1, "name": "João", "age": 30},
    {"id": 2, "name": "Maria", "age": 25}
  ]',
  '$[*]' COLUMNS (
    id INT PATH '$.id',
    name TEXT PATH '$.name',
    age INT PATH '$.age'
  )
) AS users;

-- Output:
-- id | name  | age
-- 1  | João  | 30
-- 2  | Maria | 25

Índices BRIN mais eficientes

-- Índices BRIN agora suportam mais operadores
CREATE INDEX idx_logs_created_brin 
ON logs USING BRIN (created_at)
WITH (pages_per_range = 128);

-- PG 16: Suporte a MIN/MAX melhorado
-- Queries de intervalo 40% mais rápidas

5. Segurança

pg_read_all_data e pg_write_all_data roles

-- Simplifique permissões
-- Antes: Precisava GRANT em cada tabela
GRANT SELECT ON ALL TABLES IN SCHEMA public TO usuario_readonly;

-- Agora: Role pré-definida
GRANT pg_read_all_data TO usuario_readonly;
-- Acesso leitura a TODAS as tabelas presentes e futuras

-- Para escrita
GRANT pg_write_all_data TO usuario_app;

SCRAM-SHA-256 por padrão

# postgresql.conf
password_encryption = 'scram-sha-256'  # Padrão no PG 16

-- Senhas mais seguras automaticamente
-- Substitui MD5 (inseguro)

6. Desenvolvimento e SQL

ANY_VALUE() - Agregação simplificada

-- Antes: Precisava listar todas as colunas não-agregadas
SELECT 
  customer_id,
  MAX(name),  -- Gambiarra
  MAX(email), -- Gambiarra
  SUM(amount)
FROM orders
GROUP BY customer_id;

-- PG 16: Use ANY_VALUE()
SELECT 
  customer_id,
  ANY_VALUE(name),   -- Muito mais claro!
  ANY_VALUE(email),
  SUM(amount)
FROM orders
GROUP BY customer_id;

Suporte a expressões regulares Unicode

-- Regex com Unicode completo
SELECT 'café' ~ '\w+';        -- true (agora funciona com acentos)
SELECT 'João123' ~ '^[\p{L}\p{N}]+
  

;  -- true (letras + números Unicode)

COPY com encoding on-the-fly

-- Converta encoding durante COPY
COPY users FROM '/data/users.csv'
WITH (FORMAT csv, ENCODING 'LATIN1');
-- Banco em UTF8, arquivo em LATIN1 → conversão automática

7. Vacuum e autovacuum melhorados

Vacuum paralelo mais inteligente

-- Vacuum em paralelo agora mais eficiente
VACUUM (PARALLEL 4) large_table;
-- PG 16: 50% mais rápido que PG 15

Estratégias de I/O otimizadas

-- Configuração para não sobrecarregar sistema
vacuum_buffer_usage_limit = '2GB';  -- Novo no PG 16
-- Limita memória usada por VACUUM

8. Backup e recuperação

pg_basebackup mais rápido

-- Compressão server-side (não precisa compactar localmente)
pg_basebackup -D /backup -Fp --compress=server-zstd:5

-- PG 16: Até 3x mais rápido + menos uso de rede

Recuperação incremental (PITR melhorado)

# recovery.conf (agora postgresql.auto.conf)
restore_command = 'cp /archive/%f %p'
recovery_target_time = '2026-02-17 10:30:00'
recovery_target_action = 'promote'

-- PG 16: Recuperação 40% mais rápida

9. Mudanças importantes (Breaking changes)

⚠️ public schema não mais acessível por padrão

-- Antes (PG 15): Todos podiam criar objetos em public
-- Agora (PG 16): Precisa permissão explícita

-- Dê permissão se necessário
GRANT CREATE ON SCHEMA public TO usuario;

⚠️ Algumas funções descontinuadas

-- Removido: to_timestamp(double precision)
-- Use: to_timestamp(bigint) ou to_timestamp(text)

-- Removido: suporte a Python 2
-- Use: PL/Python3 apenas

10. Upgrade para PostgreSQL 16

Teste de compatibilidade

# Use pg_upgrade em modo check
pg_upgrade \\
  --old-bindir /usr/lib/postgresql/15/bin \\
  --new-bindir /usr/lib/postgresql/16/bin \\
  --old-datadir /var/lib/postgresql/15/data \\
  --new-datadir /var/lib/postgresql/16/data \\
  --check

# Se tudo OK, remova --check e execute de verdade

Checklist pré-upgrade

□ Backup completo
□ Testar em staging primeiro
□ Verificar extensions compatíveis
□ Revisar breaking changes
□ Planejar janela de manutenção
□ Documentar rollback plan
□ Atualizar connection strings (se mudar porta)
□ Testar aplicação pós-upgrade
□ Monitorar performance (pode melhorar!)

11. PostgreSQL 16 no CloudPG

No CloudPG, você pode criar instâncias PostgreSQL 16 com 1 clique:

Conclusão

PostgreSQL 16 é uma versão essencial para produção, trazendo:

  1. ✅ Performance - Até 3x mais rápido em queries complexas
  2. ✅ Replicação lógica - Muito mais flexível e poderosa
  3. ✅ Monitoramento - Observabilidade de I/O detalhada
  4. ✅ Segurança - Roles simplificadas, SCRAM padrão
  5. ✅ DX melhorada - ANY_VALUE, JSON_TABLE, regex Unicode

Se você está no PG 15 ou anterior, vale muito a pena fazer upgrade.

Use PostgreSQL 16 hoje

Crie seu cluster PostgreSQL 16 com todos os recursos novos configurados e otimizados desde o primeiro minuto.