Параллельность в postgres в ctas с собственным агрегатом

Рейтинг: 1Ответов: 0Опубликовано: 23.07.2025

Всем доброго

Поймал такое странное поведение Postgres:

  1. Создаём собственный агрегат
  2. Помечаем его как parallel = restricted
  3. Заставляем postgres выбрать параллельный план выполнения
  4. Пишем запрос со своим агрегатом, убеждаемся, что он работает
  5. Пишем выражение create table as select с нашим запросом
  6. Получаем ошибку

Для воспроизведения:

set max_parallel_workers_per_gather = 8;
set parallel_setup_cost = 0;
set parallel_tuple_cost = 0;

drop function if exists t_positive_sfunc cascade;
create function t_positive_sfunc (
  i_balance numeric
, i_ccy_amt numeric
) returns numeric language sql parallel safe as $$
  select greatest ( i_balance + coalesce ( i_ccy_amt, 0), 0);
$$;

drop aggregate if exists t_positive ( numeric);
create or replace aggregate t_positive ( numeric) (
  sfunc    = t_positive_sfunc
, stype    = numeric
, initcond = 0
, parallel = restricted
);

drop table if exists test_data;
create table test_data as
  select 1 as part_id, 1 as order_id, 1 as value union all
  select 1 as part_id, 2 as order_id, 1 as value union all
  select 2 as part_id, 1 as order_id, 1 as value union all
  select 3 as part_id, 1 as order_id, 1 as value;
alter table test_data set ( parallel_workers = 8);

select t.part_id
     , t.order_id
     , t.value
     , t_positive ( t.value)
       over ( partition by t.part_id
                  order by t.order_id) as positive_value 
  from test_data t;

drop table if exists test_func;
create table test_func as
  select t.part_id
       , t.order_id
       , t.value
       , t_positive ( t.value)
         over ( partition by t.part_id
                    order by t.order_id) as positive_value 
    from test_data t;

Получаемая ошибка:

[Code: 0, SQL State: XX000]  ERROR: cannot start commands during a parallel operation
  Где: SQL function "t_positive_sfunc"

Может кто сталкивался?
Версия postgresql - 16.8


Да, можно поставить parallel unsafe
Но хочется добиться параллельноло выполнения
Поэтому, собственно, и ctas, а не insert


Update - решил проблему, функцию t_positive_sfunc надо отметить как immutable и все работает
Не понятна механика, конечно
Почему тогда в целом параллельный запрос работает, и падает только в ctas

Ответы

Ответов пока нет.