=> 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)
В данном случае дело в том, что пересылка всех строк таблицы между процессами невыгодна.