Tenho um banco de dados PostgreSQL 16 configurado com a seguinte configuração:
-- DB Version: 16
-- OS Type: linux
-- DB Type: oltp
-- Total Memory (RAM): 64 GB
-- CPUs num: 32
-- Connections num: 200
-- Data Storage: ssd
show effective_cache_size; --48 GB
show effective_io_concurrency; --200
show huge_pages; --try
show maintenance_work_mem; --4GB
show max_connections; --200
show max_parallel_maintenance_workers; --4
show max_parallel_workers; --32
show max_parallel_workers_per_gather; --4
show max_wal_size; --8GB
show max_worker_processes; --32
show min_wal_size; --2GB
show parallel_setup_cost; --0.1
show random_page_cost; --1.1
show shared_buffers; --16GB
show wal_buffers; --16MB
show work_mem; --256MB
Estou executando uma CREATE TABLE
consulta com múltiplas junções. Às vezes, a consulta é executada em paralelo, mas outras vezes não. Quero garantir que a consulta seja executada em paralelo ou, pelo menos, aumentar as chances de ela ser executada em paralelo para aquela sessão de transação específica. Também é bom se os trabalhadores paralelos atribuídos forem menos do que o normal, porque sem trabalhadores paralelos a consulta é muito lenta.
A configuração abaixo funcionou melhor para mim por algum tempo, mas causou um erro semelhante a este problema .
ALTER SYSTEM SET maintenance_work_mem = '8GB';
ALTER SYSTEM SET work_mem = '2GB';
ALTER SYSTEM SET effective_io_concurrency = '400';
ALTER SYSTEM SET max_parallel_workers_per_gather = '16';
ALTER SYSTEM SET wal_buffers = '1GB';
Estou anexando um plano de consulta selecionado para referência: plano de consulta .
Quero maximizar a utilização da CPU (atualmente menos de 10%) e a utilização da RAM (atualmente menos de 30%).
Estou ciente de que force_parallel_mode
foi descontinuado. Como posso obter execução paralela consistente para minhas consultas no PostgreSQL?
Você não deve forçar o PostgreSQL a usar consulta paralela. Em vez disso, diga a ele que ele pode usar muitos processos de trabalho paralelos para sua consulta se ele achar que um plano paralelo vencerá:
Você pode substituir a heurística do PostgreSQL para determinar o número de trabalhadores paralelos para varreduras de uma determinada tabela:
Você pode diminuir
min_parallel_table_scan_size
emin_parallel_index_scan_size
fazer com que a heurística do PostgreSQL escolha mais processos de trabalho paralelos.Na verdade,
force_parallel_mode
foi renomeado apenas paradebug_parallel_query
no Postgres 16. As notas de lançamento :Você pode usar essa configuração para forçar o modo paralelo. Somente na sua sessão:
Como o novo nome sugere, ele é realmente usado para depuração, porque você pode forçar o Postgres a adotar um plano de consulta ruim.
Além disso, com essa configuração, o Postgres planejará um
Gather
nó sempre que possível, mas só usará trabalhadores paralelos se algum estiver disponível no momento da execução.As duas respostas que você já tem estão, em sua maioria, corretas. Você pode usar debug_parallel_query, mas é uma maneira um tanto extrema de fazer isso e pode resultar no uso de planos paralelos, mesmo quando eles são realmente mais lentos. Nas minhas mãos, fazer isso geralmente resultará em um plano bobo que é "Cópia Única" e inicia apenas um trabalhador e faz com que esse trabalhador faça todo o trabalho (sem participação do líder).
Definir parallel_workers em uma tabela não mudará (até onde eu sei) se um plano paralelo é escolhido, mas apenas mudará quantos workers são iniciados se um plano paralelo for escolhido, então isso provavelmente não ajudará você. Alterar min_parallel_table_scan_size e min_parallel_index_scan_size ajudará você somente se essas forem as razões específicas pelas quais você não está obtendo planos paralelos, o que, com base na sua descrição, suspeito que não seja o caso (ajudaria ver um plano EXPLAIN para o caso em que ele escolhe não usar consulta paralela).
O botão mais poderoso que você tem aqui é parallel_tuple_cost. Definir como zero seria um pouco extremo (mas não tanto quanto usar debug_parallel_query). Costumo defini-lo como zero ao testar, se quiser encorajar um plano paralelo para ver o que vai acontecer. Mas eu provavelmente não faria isso em produção. Acho que o valor mínimo sensato para isso é cerca de 0,01 (um décimo do padrão) e é com isso que eu começaria na sua situação, onde você já sabe que a consulta paralela está sendo subutilizada.
A configuração correta para isso vai depender do uso do seu servidor. Se apenas uma conexão de banco de dados provavelmente estiver ativa por vez, então qualquer CPU não usada para essa conexão será desperdiçada, então essa situação justifica as configurações mais baixas para cpu_tuple_cost. Por outro lado, se o servidor estiver muito ocupado, de modo que muitas sessões estejam ativas ao mesmo tempo e lutem pela CPU, usar a consulta paralela só fará com que elas lutem mais, o que sugeriria uma configuração mais alta para cpu_tuple_cost (ou, no extremo, apenas alterar max_parallel_workers_per_gather=0 para desabilitar a consulta paralela completamente).