У меня есть пользовательский агрегатная функция суммы, которая принимает булев тип данных:Повышение производительности пользовательской функции совокупной в PostgreSQL
create or replace function badd (bigint, boolean)
returns bigint as
$body$
select $1 + case when $2 then 1 else 0 end;
$body$ language sql;
create aggregate sum(boolean) (
sfunc=badd,
stype=int8,
initcond='0'
);
Этого агрегат должен рассчитать количество строк с TRUE
. Например, следующий должен вернуть 2 (и делает):
with t (x) as
(values
(true::boolean),
(false::boolean),
(true::boolean),
(null::boolean)
)
select sum(x) from t;
Однако, его производительность очень плохо, это в 5,5 раза медленнее, чем с помощью литья в целое:
with t as (select (gs > 0.5) as test_vector from generate_series(1,1000000,1) gs)
select sum(test_vector) from t; -- 52012ms
with t as (select (gs > 0.5) as test_vector from generate_series(1,1000000,1) gs)
select sum(test_vector::int) from t; -- 9484ms
Это единственный способ как улучшить этот агрегат, чтобы написать некоторую новую функцию C - например некоторая альтернатива int2_sum
функция в src/backend/utils/adt/numeric.c
?
Это не int2-сумма. Это суммарная сумма, которая больше похожа на бит-1. И это тоже неправильно. Он должен быть: '$ 1 + $ 2 :: int', или' $ 1 + case $ 2, когда true, а затем 1 else 0 end', или что-то в этом порядке. –
Я по-прежнему не вижу причины для настраиваемой совокупности, как 'select sum (x :: int) из t;' и 'select sum (1) из t, где x;' являются правильными и намного быстрее – foibs
@Denis I обновил мой вопрос, мой агрегат работает правильно и делает то, что я хочу, но он медленный. –