15.2. Когда можно использовать параллельные запросы?#
15.2. Когда можно использовать параллельные запросы? #
Все настройки, которые могут привести к тому, что планировщик запросов не будет генерировать параллельные планы запросов ни при каких обстоятельствах, должны быть настроены следующим образом, чтобы вообще генерировались параллельные планы запросов.
max_parallel_workers_per_gather должно быть установлено на значение, большее нуля. Это особый случай более общего принципа, что количество рабочих процессов не должно превышать число, настроенное через
max_parallel_workers_per_gather
.
Кроме того, система не должна работать в однопользовательском режиме. Поскольку в этой ситуации вся система базы данных работает как один процесс, фоновые рабочие процессы не будут доступны.
Даже когда в общем случае возможно генерировать параллельные планы запросов, планировщик не будет генерировать их для данного запроса, если выполняется хотя бы одно из следующих условий:
Запрос записывает любые данные или блокирует любые строки базы данных. Если запрос содержит операцию модификации данных на верхнем уровне или внутри CTE, для этого запроса не будут созданы параллельные планы. Однако следующие команды, которые создают новую таблицу и заполняют ее, могут использовать параллельный план для основной части запроса
SELECT
:CREATE TABLE ... AS
SELECT INTO
CREATE MATERIALIZED VIEW
REFRESH MATERIALIZED VIEW
В любой ситуации, когда система считает, что может произойти частичное или инкрементное выполнение, запрос может быть приостановлен. В таких случаях не генерируется параллельный план. Например, курсор, созданный с помощью DECLARE CURSOR, никогда не будет использовать параллельный план. Аналогично, цикл PL/pgSQL вида
FOR x IN query LOOP .. END LOOP
никогда не будет использовать параллельный план, потому что параллельная система запросов не может проверить, что код внутри цикла безопасен для выполнения во время активного параллельного запроса.Запрос использует любую функцию, помеченную как
PARALLEL UNSAFE
. Большинство системных функций являютсяPARALLEL SAFE
, но пользовательские функции по умолчанию помечены какPARALLEL UNSAFE
. См. обсуждение Раздел 15.4.Запрос выполняется внутри другого запроса, который уже выполняется параллельно. Например, если функция, вызванная параллельным запросом, выполняет сама SQL-запрос, этот запрос никогда не будет использовать параллельный план. Это ограничение текущей реализации, но может быть нежелательно удалять это ограничение, так как это может привести к использованию очень большого количества процессов в одном запросе.
Даже когда для конкретного запроса создается параллельный план запроса, существуют несколько обстоятельств, при которых выполнение этого плана параллельно во время выполнения будет невозможно. Если это произойдет, лидер выполнит часть плана ниже узла Gather
полностью самостоятельно, почти так, как если бы узел Gather
не присутствовал. Это произойдет, если выполнено любое из следующих условий:
Невозможно получить фоновые рабочие процессы из-за ограничения, согласно которому общее количество фоновых рабочих процессов не может превышать max_worker_processes.
Невозможно получить фоновые рабочие процессы из-за ограничения, согласно которому общее количество фоновых рабочих процессов, запущенных для выполнения параллельных запросов, не может превышать max_parallel_workers.
Клиент отправляет сообщение Execute с ненулевым значением fetch count. См. обсуждение расширенного протокола запроса. Поскольку libpq в настоящее время не предоставляет способа отправки такого сообщения, это может произойти только при использовании клиента, который не полагается на libpq. Если это частое явление, может быть хорошей идеей установить max_parallel_workers_per_gather в ноль в сессиях, где это вероятно, чтобы избежать создания планов запросов, которые могут быть неоптимальными при последовательном выполнении.