Eu trabalho com PostgreSQL 12 e tenho tabelas particionadas que estou tentando agrupar. Cada partição tem aproximadamente o mesmo tamanho em termos de GB. No entanto, o desempenho pode variar significativamente, variando de 5 a 1.000 minutos de tempo de cluster por partição.
Estou agrupando várias partições em cluster em paralelo e meu banco de dados não está recebendo nenhuma solicitação além das solicitações CLUSTER.
Não entendo completamente os meandros do processo CLUSTER nos bastidores. O que poderia explicar variações tão grandes no tempo de agrupamento e o que posso fazer para melhorar o desempenho?
EDIT: Para ser mais preciso, tenho uma partição de 34 GB agrupada em cluster em 13 minutos e uma partição de 56 GB agrupada em cluster em 1288 minutos (quase um dia). Esses valores de tamanho são o tamanho antes do cluster. Estou recalculando os tamanhos.
Consulta usada para recuperar o tamanho:
SELECT table_name,
pg_size_pretty(pg_total_relation_size(table_schema || '."' || table_name || '"')) AS size
FROM information_schema.tables
WHERE table_schema = 'partitionschema' and table_name like 'mytable_%' order by table_name;
Eu não fiz ANALYZE ou VACUUM antes de agrupar.
Tenho E/S de disco de 900 MB/s e 128 GB de RAM (embora apenas 40 pareçam ser usados de acordo com meu painel do datadog). Também não parece que meus processadores sejam uma limitação.
Tenho 300 partições para agrupar, em cada etapa do processo, estou tentando agrupar 8 partições em paralelo. Cada uma dessas partições está em ~ 50 GB
Algumas outras informações:
- manutenção_work_mem: 4 GB
- trabalho_meme: 64 MB
- buffer_compartilhado: 32 GB
- max_wal_size: 4 GB
Finalmente encontrei minha resposta!
Na documentação é mencionado que CLUSTER pode utilizar 2 métodos para obter dados da tabela onde o CLUSTER está aplicado.
Varredura de índice: mais lenta, classifica os dados progressivamente, lendo os dados diretamente de forma classificada por meio de uma varredura de índice.
Varredura sequencial: leia todos os dados sequencialmente e, em seguida, classifique-os. A operação precisa usar um arquivo temporário se ele não couber na memória RAM, portanto, potencialmente consumirá espaço em disco.
Por padrão, o método é escolhido automaticamente, mas você pode forçar uma varredura de índice com
set enable_sort = 'off;
e uma varredura de sequência comset enable_indexscan = 'off;'
Na minha tabela de aproximadamente 150 milhões de linhas, verificando a tabela
pg_stat_progress_cluster
, a velocidade de leitura da varredura de índice foi de 100-300 tuplas/seg, versus 100 mil tuplas/seg para a varredura Seq.Eu estava usando a configuração de planejamento automático padrão e acho que no meu primeiro exemplo foi usado um Seq Scan e um Index Scan no meu segundo cluster.
Minha solução final foi executar
Ainda não entendo totalmente por que minha varredura de índice é tão lenta, mas provavelmente terei que conviver com isso.