Средняя стоимость перелета

=> 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)

В данном случае дело в том, что пересылка всех строк таблицы между процессами невыгодна.