=> EXPLAIN SELECT avg(amount) FROM ticket_flights;
QUERY PLAN ---------------------------------------------------------------------------------------------------- Finalize Aggregate (cost=110786.07..110786.08 rows=1 width=32) -> Gather (cost=110785.85..110786.06 rows=2 width=32) Workers Planned: 2 -> Partial Aggregate (cost=109785.85..109785.86 rows=1 width=32) -> Parallel Seq Scan on ticket_flights (cost=0.00..101044.27 rows=3496628 width=6) (5 rows)
Планировщик выбирает параллельный план.
=> EXPLAIN WITH tf AS ( SELECT * FROM ticket_flights ) SELECT avg(amount) FROM tf;
QUERY PLAN ---------------------------------------------------------------------------------- Aggregate (cost=338814.95..338814.96 rows=1 width=32) CTE tf -> Seq Scan on ticket_flights (cost=0.00..149997.06 rows=8391906 width=32) -> CTE Scan on tf (cost=0.00..167838.12 rows=8391906 width=16) (4 rows)
Здесь узел CTE представляет подзапрос в общем табличном выражении.
Затем выполняется узел CTE Scan: по сути он работает так же, как и Seq Scan, но просматривает не таблицу, а полученный и материализованный результат выполнения подзапроса. Эта операция выполняется последовательно.
При этом сам подзапрос в общем табличном выражении может работать параллельно:
=> EXPLAIN WITH x AS ( SELECT avg(amount) FROM ticket_flights ) SELECT * FROM x;
QUERY PLAN ------------------------------------------------------------------------------------------------------------ CTE Scan on x (cost=110786.08..110786.10 rows=1 width=32) CTE x -> Finalize Aggregate (cost=110786.07..110786.08 rows=1 width=32) -> Gather (cost=110785.85..110786.06 rows=2 width=32) Workers Planned: 2 -> Partial Aggregate (cost=109785.85..109785.86 rows=1 width=32) -> Parallel Seq Scan on ticket_flights (cost=0.00..101044.27 rows=3496628 width=6) (7 rows)
=> EXPLAIN SELECT * FROM flights;
QUERY PLAN ---------------------------------------------------------------- Seq Scan on flights (cost=0.00..4564.67 rows=214867 width=63) (1 row)
Размер таблицы достаточно большой, чтобы планировщик рассмотрел параллельный план:
=> SELECT pg_size_pretty(pg_table_size('flights')) size;
size ------- 19 MB (1 row)
Используя конфигурационный параметр можно убедиться, что запрос в принципе не запрещает параллельное выполнение, но планировщик отказывается от такой возможности из-за ее неэффективности:
=> SET force_parallel_mode = on;
SET
=> EXPLAIN SELECT * FROM flights;
QUERY PLAN ---------------------------------------------------------------------- Gather (cost=1000.00..27051.37 rows=214867 width=63) Workers Planned: 1 Single Copy: true -> Seq Scan on flights (cost=0.00..4564.67 rows=214867 width=63) (4 rows)
В данном случае дело в том, что пересылка всех строк таблицы между процессами невыгодна.