Como deixar o Postgres lento
(byteofdev.com)- Introdução a uma abordagem experimental sobre combinações de parâmetros que podem degradar drasticamente o desempenho do Postgres
- Em vez de otimizar, o texto ajusta ao contrário vários elementos como cache, índices, WAL e I/O
- Ao manipular de forma extrema shared_buffers, autovacuum e opções relacionadas a WAL, foi alcançada uma queda de TPS de 42.000 vezes
- Também foram aplicados recursos recentes como io_method e io_workers das novas versões Postgres 18/19 para testar a limitação a uma única thread de I/O
- O experimento demonstra que é possível provocar degradação extrema de desempenho apenas com o arquivo de configuração do Postgres
Visão geral
Este texto apresenta um experimento que faz o oposto do ajuste de Postgres normalmente voltado a deixá-lo mais rápido: o único objetivo é deixá-lo lento, alterando apenas vários valores de configuração do PostgreSQL para degradar o desempenho até o limite.
O teste foi baseado na carga TPC-C do BenchBase (128 armazéns, 100 conexões, tentativa de até 10.000 transações por segundo para cada uma, Postgres 19devel mais recente, Ryzen 7950x, 32 GB de RAM, SSD de 2 TB, execução por 120 segundos).
Com os valores padrão, o desempenho era de 7082 TPS, e foi observado passo a passo o quanto ele ficava mais lento com cada manipulação de parâmetro.
Reduzindo drasticamente o cache
- O Postgres usa um cache poderoso (
shared_buffers) para reduzir I/O de disco - Ao reduzir
shared_buffersde 10 GB para 8 MB, o TPS caiu para cerca de 1/7 (1052 TPS) - A taxa de cache hit caiu de 99,90% para 70,52%, e foi observado um aumento de mais de 300 vezes nas syscalls de leitura
- Houve tentativa de reduzir até 128 kB, mas o Postgres só permitiu cerca de 2 MB como mínimo, levando a nova queda para 485 TPS
Aumentando o trabalho em segundo plano (ajuste de autovacuum)
- Todos os limiares relacionados a
autovacuumforam colocados no mínimo, fazendo com que o vacuum rodasse praticamente a cada operação- Combinação como
autovacuum_vacuum_insert_threshold=1,autovacuum_naptime=1etc. - Mesmo quando não havia trabalho real a fazer, o vacuum se repetia quase a cada 1 segundo
- Combinação como
- Nesse processo,
maintenance_work_memfoi reduzido para 128 kB, e todo o logging de autovacuum foi ativado - Como resultado, o TPS caiu para 293 (menos de 1/20 do original)
- Pelos logs em tempo real de autovacuum, foi confirmado que o desempenho piorava devido ao trabalho frequente em segundo plano
Tornando a gravação de WAL (Write-Ahead Log) a pior possível
- Os parâmetros relacionados a WAL foram ajustados todos para o pior cenário
wal_writer_flush_after=0,wal_writer_delay=1,wal_sync_method=open_datasyncetc.- Checkpoints forçados a cada 30 segundos, com
min/max_wal_size=32MBmantidos no mínimo wal_level=logical,wal_log_hints=one até informações desnecessárias sendo gravadas no WAL- Cargas extras como
track_wal_io_timingesummarize_waltambém foram ativadas
- Com isso, o TPS caiu para 98 (menos de 1/70 do original)
- Nos logs, foi observado comportamento anormal, como checkpoints se repetindo a cada poucas centenas de ms
Eliminando o efeito dos índices
- O uso de índices foi configurado para que todos fossem calculados com custo máximo (
random_page_cost=1e300,cpu_index_tuple_cost=1e300), inutilizando-os na prática shared_buffersfoi aumentado para 8 MB (por estabilidade), e o TPS despencou para 0,87 (atingindo 7.000 vezes mais lentidão)
Forçando I/O em thread única
- Uso de recursos mais recentes do Postgres 18+
- Com
io_method=workereio_workers=1, todo o I/O foi forçado para uma única thread worker - O TPS caiu ainda mais, para 0,016 (42.000 vezes mais lento)
- Em um teste com 100 conexões por 120 segundos, o desempenho ficou tão limitado que apenas 11 transações foram concluídas com sucesso
Conclusão e guia de reprodução
- Foi demonstrado que, com um total de 32 manipulações de parâmetros, é possível levar um banco de produção a um estado de praticamente "paralisia"
- É possível maximizar a degradação de desempenho mexendo apenas na configuração de
postgresql.conf - Quem quiser reproduzir o experimento deve consultar o BenchBase Postgres, o ambiente TPC-C descrito acima e a lista completa de configurações
- Alguns parâmetros adicionais e outras tentativas de deixá-lo ainda mais lento não foram incluídos
Lista resumida de parâmetros
shared_buffers = 8MB- thresholds/
scale_factorrelacionados aautovacuum= minimizados para 0~1 - custos, memória e logs relacionados a vacuum: mínimo & máximo
- sync/flush/log/nível relacionados a WAL: mantidos no modo mais lento
random_page_cost,cpu_index_tuple_costligados a índice: definidos como1e300io_method = worker,io_workers = 1- Para outros valores detalhados, consultar a lista no corpo do texto
Encerramento
- É possível provocar degradação severa de desempenho apenas com o arquivo
postgresql.conf - Na prática, vale a pena usar essa combinação ao contrário como referência para melhoria eficiente de desempenho
- O texto termina mencionando a interrupção do experimento por causa de dor nas costas do autor
2 comentários
Opiniões no Hacker News
Excelente. Gosto muito desse tipo de abordagem.