Postgres 9.6: параллельный запрос не требует настройки max_parallel_workers_per_gather

Postgres 9.6; Centos 6.7; 24 ядра

BigTable1 содержит 1 500 000 000 строк; вес 180гб.

max_worker_processes = 20
max_parallel_workers_per_gather = 12

1) При беге

EXPLAIN
SELECT
    date_id, id1, id2, id3, id4, topdomain, ftype, SUM(imps), SUM(cls)
FROM BigTable1
WHERE
    date_id BETWEEN 2017021200 AND 2017022400             
    AND date_id BETWEEN 2017020000 AND 2017029999   
GROUP BY
date_id, id1, id2, id3, id4, topdomain, ftype;

Никакие «Планируемые рабочие»: вообще не используются. Почему?

2) При запуске того же запроса в определенном сеансе

set max_parallel_workers_per_gather = 5;

Появляется сообщение «Запланировано рабочих: 5». Время выполнения улучшилось всего на 25%.

2.1) Почему «Планируемые рабочие:» появляется только после этой настройки? 2.2) Почему при работе с max_parallel_workers_per_gather = 5 мы не смогли увидеть более значительных улучшений?

Спасибо!.


person Anya    schedule 02.03.2017    source источник
comment
Какое у вас оборудование? Сколько дисков? Какие диски? А как быстро твои диски? А что с оперативной памятью? И Т. Д.   -  person Frank Heikens    schedule 02.03.2017


Ответы (2)


Когда PostgreSQL рассматривает параллельное последовательное сканирование, он решает, сколько рабочих процессов следует использовать, в зависимости от размера отношения (или параметра хранения parallel_workers для управляющей таблицы) и вычисляет стоимость параллельного плана с этим количеством рабочих. Это сравнивается со стоимостью серийного плана, и более дешевый план выигрывает. Планы с другим количеством рабочих не рассматриваются, поэтому может случиться так, что стоимость серийного плана меньше, чем стоимость рассматриваемого плана, но больше, чем стоимость некоторого плана с другим числом рабочих. Вероятно, это произошло в вашем случае.

Поскольку вы не публиковали вывод EXPLAIN ANALYZE, мы не можем видеть, сколько групп создает ваш запрос, но я предполагаю, что это довольно большое количество. В PostgreSQL 9.6 параллельное агрегирование должно выполняться путем агрегирования части данных в каждом работнике (PartialAggregate) и последующего объединения групп с одинаковыми ключами в ведущем (FinalizeAggregate). Между этими двумя шагами требуется узел Gather для передачи частично сгруппированных данных от рабочих к лидеру. Этот узел Gather довольно дорогой, поэтому наиболее вероятная причина, по которой вы видели только ограниченное ускорение, заключается в том, что количество передаваемых групп было большим. Стоимость отправки всех этих групп и слияния групп, которые произошли у более чем одного рабочего, могла казаться слишком высокой, чтобы оправдать параллелизм с большим числом рабочих, но могла выглядеть как выигрыш с меньшим числом рабочих. Эти же затраты, вероятно, объясняют тот факт, что даже при использовании параллельного запроса вы увидели только 25% ускорение.

Если вы опубликуете вывод EXPLAIN ANALYZE с параллельным запросом и без него (то есть с «Workers Planned: 5» и без параллелизма), возможно, появится возможность более четко понять, что происходит в вашем случае.

(Источник: я являюсь одним из основных авторов поддержки параллельных запросов PostgreSQL.)

person Robert Haas    schedule 27.03.2017

Если вы просто хотите протестировать биты параллельного запроса, вы можете взглянуть на force_parallel_mode и включить его.

force_parallel_mode (перечисление)

Позволяет использовать параллельные запросы для целей тестирования даже в тех случаях, когда не ожидается увеличения производительности. Допустимые значения force_parallel_mode выключены (используйте параллельный режим только тогда, когда ожидается, что он улучшит производительность), on (принудительный параллельный запрос для всех запросов, для которых он считается безопасным) и регресс (например, on, но с дополнительными изменениями поведения как объяснено ниже).

И, как упомянуто ниже robert-haas, без force_parallel_mode оптимизатор потенциально решит, что параллельный запрос не самый быстрый. .. см. параметры ниже:

select
  name,
  setting,
  unit,
  short_desc
from pg_settings
where name in (
  'force_parallel_mode',
  'min_parallel_relation_size',
  'parallel_setup_cost',
  'parallel_tuble_cost',
  'max_parallel_workers_per_gather' )
  limit 10 ;

postgres=> 
---------------------------------+---------+------+---------------------------------------------------------------------------------------------
 force_parallel_mode             | off     |      | Forces use of parallel query facilities.
 max_parallel_workers_per_gather | 0       |      | Sets the maximum number of parallel processes per executor node.
 min_parallel_relation_size      | 1024    | 8kB  | Sets the minimum size of relations to be considered for parallel scan.
 parallel_setup_cost             | 1000    |      | Sets the planner's estimate of the cost of starting up worker processes for parallel query.
(4 rows)
person joefromct    schedule 29.03.2017