notes/db/sql/postgres/feature/query/parallel-mode.txt
Ihar Hancharenka 34be9dd7e3 m
2024-06-28 16:35:21 +03:00

46 строки
6.6 KiB
Plaintext

*****************************************************************************
Если у вас в PostgreSQL включено параллельное выполнение запросов, то планировщик, в целях повышения производительности выполнения запроса может решить использовать его. Что такое параллельное выполнение запросов, как работает и как его настроить будем разбираться в этой заметке.
Технически параллельное выполнение запросов происходит так: запрос разбивается на несколько частей и выполняется несколькими фоновыми процессами. Фоновые процессы общаются между собой через общий буфуер. Как только каждая часть запроса будет выполнена, его результат будет аккомулирован и передан ведущему процессу.
Результат команды EXPLAIN при параллельном выполнении запроса будет выглядеть примерно вот так:
Gather (cost=0.00..46010.00 rows=1000000 width=43)
Workers Planned: 4
Workers Launched: 4
-> Parallel Seq Scan on my_table (cost=0.00..44010.00 rows=230000 width=43)
Вместо Gather еще может быть Gather Merge. В чем разница, разберемся дальше.
Здесь Gather показывает нам, что результат запроса был собран из нескольких параллельных процессов, Workers Planned - сколько параллельных процессов было запланировано к использованию планировщиком запросов, Workers Launched - сколько фактически параллельных процессов было использовано.
Разница между Gather и Gather Merge заключается в том, что Gather Merge участвует в операциях сортировки (ORDER BY), т.е. когда каждый из фоновых процессов производит сортировку своей части запроса и передает результат для финального слияния ведущему процессу. Gather используется в запросах без сортировки.
Есть несколько параметров в файле postgresql.conf, с помощью которых мы можем управлять параллельным выполнением запросов:
max_worker_processes - контролирует общее кол-во фоновых процессов, доступных всему кластеру PostgreSQL;
max_parallel_workers - контролирует общее кол-во активных процессов, доступных всему кластеру PostgreSQL для параллельного выполнения запросов. Значение этого параметра должно быть меньшим или равным значению параметра max_worker_processes;
max_parallel_workers_per_gather - значение этого параметра контролирует кол-во фоновых процессов, доступных для параллельного выполнения одного запроса.
Есть еще несколько параметров, с помощью которых мы можем контролировать стоимость выполнения параллельных запросов:
parallel_setup_cost - устанавливает стоимость запуска одного фонового процесса и выделения ему памяти. Значение по умолчанию 1000;
parallel_tuple_cost - устанавливает стоимость передачи данных между фоновыми процессами. Значение по умолчанию 0.1.
А еще мы можем управлять параллельным сканированием таблиц и индексов:
min_parallel_table_scan_size - устанавливает минимальный размер таблицы, при котором PostgreSQL примет решение о ее параллельном сканировании. Значение устанавливается в байтах, значение по умолчанию - 8MB. Т.е. параллельное сканирование не будет включаться на таблицах, объем которых меньше 8MB;
min_parallel_index_scan_size - тоже самое, что и предыдущий параметр, только для индексов. Значение по умолчанию 8MB.
А еще можно включить параметр force_parallel_mode (по умолчанию OFF) и тогда PostgreSQL будет пытаться параллелить все что возможно. Но на рабочем кластере лучше так не делать, так как могут быть неприятные нюансы.
Параллельное выполнение запросов наиболее эффективно при OLAP нагрузке, т.е. когда у вас в базе происходят долгие запросы для формирования какого-нибудь аналитического отчета. Когда у вас много коротких запросов, которые создают, обновляют или удаляют данные в базе, т.е. OLTP нагрузка, то толку от параллельного выполнения запросов будет мало, или не будет вообще.
Для программ семейства 1с вообще рекомендуют отключать параллелизм, т.е. ставить параметр max_parallel_workers_per_gather в ноль, но тут все не так просто и настройки параллелизма могут зависеть от конкретной ситуации и типа нагрузки на базу данных.
О нюансах параллелизма запросов ещё расскажем в будущих постах 😉.