mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-14 17:43:34 +08:00
Make `partialize_agg()` support parallel query execution. To make this work, the finalize node need combine the individual partials from each parallel worker, but the final step that turns the resulting partial into the finished aggregate should not happen. Thus, in the case of distributed hypertables, each data node can run a parallel query to compute a partial, and the access node can later combine and finalize these partials into the final aggregate. Esssentially, there will be one combine step (minus final) on each data node, and then another one plus final on the access node. To implement this, the finalize aggregate plan is simply modified to elide the final step, and to reserialize the partial. It is only possible to do this at the plan stage; if done at the path stage, the PostgreSQL planner will hit assertions that assume that the node has certain values (e.g., it doesn't expect combine Paths to skip the final step).
911 lines
51 KiB
Plaintext
911 lines
51 KiB
Plaintext
-- This file and its contents are licensed under the Timescale License.
|
|
-- Please see the included NOTICE for copyright information and
|
|
-- LICENSE-TIMESCALE for a copy of the license.
|
|
-- TEST1 count with integers
|
|
SHOW enable_partitionwise_aggregate;
|
|
enable_partitionwise_aggregate
|
|
--------------------------------
|
|
off
|
|
(1 row)
|
|
|
|
SET enable_partitionwise_aggregate = on;
|
|
create table foo (a integer, b integer, c integer);
|
|
insert into foo values( 1 , 10 , 20);
|
|
insert into foo values( 1 , 11 , 20);
|
|
insert into foo values( 1 , 12 , 20);
|
|
insert into foo values( 1 , 13 , 20);
|
|
insert into foo values( 1 , 14 , 20);
|
|
insert into foo values( 2 , 14 , 20);
|
|
insert into foo values( 2 , 15 , 20);
|
|
insert into foo values( 2 , 16 , 20);
|
|
insert into foo values( 3 , 16 , 20);
|
|
create or replace view v1(a , partial)
|
|
as
|
|
SELECT a, _timescaledb_internal.partialize_agg( count(b)) from foo group by a;
|
|
create table t1 as select * from v1;
|
|
select a, _timescaledb_internal.finalize_agg( 'count("any")', null, null, null, partial, cast('1' as int8) ) from t1
|
|
group by a order by a ;
|
|
a | finalize_agg
|
|
---+--------------
|
|
1 | 5
|
|
2 | 3
|
|
3 | 1
|
|
(3 rows)
|
|
|
|
insert into t1 select * from t1;
|
|
select a, _timescaledb_internal.finalize_agg( 'count("any")', null, null, null, partial, cast('1' as int8) ) from t1
|
|
group by a order by a ;
|
|
a | finalize_agg
|
|
---+--------------
|
|
1 | 10
|
|
2 | 6
|
|
3 | 2
|
|
(3 rows)
|
|
|
|
--TEST2 sum numeric and min on float--
|
|
drop table t1;
|
|
drop view v1;
|
|
drop table foo;
|
|
create table foo (a integer, b numeric , c float);
|
|
insert into foo values( 1 , 10 , 20);
|
|
insert into foo values( 1 , 20 , 19);
|
|
insert into foo values( 1 , 30 , 11.0);
|
|
insert into foo values( 1 , 40 , 200);
|
|
insert into foo values( 1 , 50 , -10);
|
|
insert into foo values( 2 , 10 , 20);
|
|
insert into foo values( 2 , 20 , 20);
|
|
insert into foo values( 2 , 30 , 20);
|
|
insert into foo values( 3 , 40 , 0);
|
|
create or replace view v1(a , partialb, partialminc)
|
|
as
|
|
SELECT a, _timescaledb_internal.partialize_agg( sum(b)) , _timescaledb_internal.partialize_agg( min(c)) from foo group by a;
|
|
create table t1 as select * from v1;
|
|
select a, _timescaledb_internal.finalize_agg( 'sum(numeric)', null, null, null, partialb, cast('1' as numeric) ) sumb, _timescaledb_internal.finalize_agg( 'min(double precision)', null, null, null, partialminc, cast('1' as float8) ) minc from t1 group by a order by a ;
|
|
a | sumb | minc
|
|
---+------+------
|
|
1 | 150 | -10
|
|
2 | 60 | 20
|
|
3 | 40 | 0
|
|
(3 rows)
|
|
|
|
insert into foo values( 3, 0, -1);
|
|
insert into foo values( 5, 40, 10);
|
|
insert into foo values( 5, 40, 0);
|
|
--note that rows for 3 get added all over again + new row
|
|
--sum aggfnoid 2114, min aggfnoid is 2136 oid numeric is 1700
|
|
insert into t1 select * from v1 where ( a = 3 ) or a = 5;
|
|
select a, _timescaledb_internal.finalize_agg( 'sum(numeric)', null, null, null, partialb, cast('1' as numeric) ) sumb, _timescaledb_internal.finalize_agg( 'min(double precision)', null, null, null, partialminc, cast('1' as float8) ) minc from t1 group by a order by a ;
|
|
a | sumb | minc
|
|
---+------+------
|
|
1 | 150 | -10
|
|
2 | 60 | 20
|
|
3 | 80 | -1
|
|
5 | 80 | 0
|
|
(4 rows)
|
|
|
|
SET enable_partitionwise_aggregate = off;
|
|
--TEST3 sum with expressions
|
|
drop table t1;
|
|
drop view v1;
|
|
drop table foo;
|
|
create table foo (a integer, b numeric , c float);
|
|
insert into foo values( 1 , 10 , 20);
|
|
insert into foo values( 1 , 20 , 19);
|
|
insert into foo values( 1 , 30 , 11.0);
|
|
insert into foo values( 1 , 40 , 200);
|
|
insert into foo values( 1 , 50 , -10);
|
|
insert into foo values( 2 , 10 , 20);
|
|
insert into foo values( 2 , 20 , 20);
|
|
insert into foo values( 2 , 30 , 20);
|
|
insert into foo values( 3 , 40 , 0);
|
|
insert into foo values(10, NULL, NULL);
|
|
insert into foo values(11, NULL, NULL);
|
|
insert into foo values(11, NULL, NULL);
|
|
insert into foo values(12, NULL, NULL);
|
|
create or replace view v1(a , b, partialb, partialminc)
|
|
as
|
|
SELECT a, b, _timescaledb_internal.partialize_agg( sum(b+c)) , _timescaledb_internal.partialize_agg( min(c)) from foo group by a, b ;
|
|
create table t1 as select * from v1;
|
|
insert into foo values( 3, 0, -1);
|
|
insert into foo values( 5, 40, 10);
|
|
insert into foo values( 5, 40, 0);
|
|
insert into foo values(12, 10, 20);
|
|
insert into t1 select * from v1 where ( a = 3 and b = 0 ) or a = 5 or (a = 12 and b = 10) ;
|
|
--results should match query: select a, sum(b+c), min(c) from foo group by a order by a;
|
|
--sum aggfnoid 2111 for float8, min aggfnoid is 2136 oid numeric is 1700
|
|
select a, _timescaledb_internal.finalize_agg( 'sum(double precision)', null, null, null, partialb, null::float8 ) sumcd, _timescaledb_internal.finalize_agg( 'min(double precision)', null, null, null, partialminc, cast('1' as float8) ) minc from t1 group by a order by a ;
|
|
a | sumcd | minc
|
|
----+-------+------
|
|
1 | 390 | -10
|
|
2 | 120 | 20
|
|
3 | 39 | -1
|
|
5 | 90 | 0
|
|
10 | |
|
|
11 | |
|
|
12 | 30 | 20
|
|
(7 rows)
|
|
|
|
insert into t1 select * from v1;
|
|
select a, _timescaledb_internal.finalize_agg( 'sum(double precision)', null, null, null, partialb, null::float8 ) sumcd, _timescaledb_internal.finalize_agg( 'min(double precision)', null, null, null, partialminc, cast('1' as float8) ) minc from t1 group by a order by a ;
|
|
a | sumcd | minc
|
|
----+-------+------
|
|
1 | 780 | -10
|
|
2 | 240 | 20
|
|
3 | 78 | -1
|
|
5 | 180 | 0
|
|
10 | |
|
|
11 | |
|
|
12 | 60 | 20
|
|
(7 rows)
|
|
|
|
-- TEST4 with collation (text), NULLS and timestamp --
|
|
drop table t1;
|
|
drop view v1;
|
|
drop table foo;
|
|
create table foo (a integer, b numeric , c text, d timestamptz, e bigint);
|
|
insert into foo values( 1 , 10 , 'hello', '2010-01-01 09:00:00-08', 10);
|
|
insert into foo values( 1 , 20 , 'abc', '2010-01-02 09:00:00-08', 20);
|
|
insert into foo values( 1 , 30 , 'abcd', '2010-01-03 09:00:00-08', 30);
|
|
insert into foo values( 1 , 40 , 'abcde', NULL, 40);
|
|
insert into foo values( 1 , 50 , NULL, '2010-01-01 09:00:00-08', 50);
|
|
--group with all values for c and d same
|
|
insert into foo values( 2 , 10 , 'hello', '2010-01-01 09:00:00-08', 10);
|
|
insert into foo values( 2 , 20 , 'hello', '2010-01-01 09:00:00-08', 20);
|
|
insert into foo values( 2 , 30 , 'hello', '2010-01-01 09:00:00-08', 30);
|
|
--group with all values for c and d NULL
|
|
insert into foo values( 3 , 40 , NULL, NULL, 40);
|
|
insert into foo values( 3 , 50 , NULL, NULL, 50);
|
|
insert into foo values(11, NULL, NULL, NULL, NULL);
|
|
insert into foo values(11, NULL, 'hello', '2010-01-02 09:00:00-05', NULL);
|
|
--group with all values for c and d NULL and later add non-null.
|
|
insert into foo values(12, NULL, NULL, NULL, NULL);
|
|
create or replace view v1(a , b, partialb, partialc, partiald, partiale, partialf)
|
|
as
|
|
SELECT a, b, _timescaledb_internal.partialize_agg(sum(b))
|
|
, _timescaledb_internal.partialize_agg(min(c))
|
|
, _timescaledb_internal.partialize_agg(max(d))
|
|
, _timescaledb_internal.partialize_agg(stddev(b))
|
|
, _timescaledb_internal.partialize_agg(stddev(e)) from foo group by a, b ;
|
|
create table t1 as select * from v1;
|
|
--sum 2114, collid 0, min(text) 2145, collid 100, max(ts) 2127
|
|
insert into foo values(12, 10, 'hello', '2010-01-02 09:00:00-05', 10);
|
|
insert into t1 select * from v1 where (a = 12 and b = 10) ;
|
|
--select a, sum(b), min(c) , max(d), stddev(b), stddev(e) from foo group by a order by a;
|
|
--results should match above query
|
|
CREATE OR REPLACE VIEW vfinal(a , sumb, minc, maxd, stddevb, stddeve)
|
|
AS
|
|
select a, _timescaledb_internal.finalize_agg( 'sum(numeric)', null, null, null, partialb, null::numeric ) sumb
|
|
, _timescaledb_internal.finalize_agg( 'min(text)', 'pg_catalog', 'default', null, partialc, null::text ) minc
|
|
, _timescaledb_internal.finalize_agg( 'max(timestamp with time zone)', null, null, null, partiald, null::timestamptz ) maxd
|
|
, _timescaledb_internal.finalize_agg( 'stddev(numeric)', null, null, null, partiale, null::numeric ) stddevb
|
|
, _timescaledb_internal.finalize_agg( 'stddev(int8)', null, null, null, partialf, null::numeric ) stddeve
|
|
from t1 group by a order by a ;
|
|
SELECT * FROM vfinal;
|
|
a | sumb | minc | maxd | stddevb | stddeve
|
|
----+------+-------+------------------------------+---------------------+---------------------
|
|
1 | 150 | abc | Sun Jan 03 09:00:00 2010 PST | 15.8113883008418967 | 15.8113883008418967
|
|
2 | 60 | hello | Fri Jan 01 09:00:00 2010 PST | 10.0000000000000000 | 10.0000000000000000
|
|
3 | 90 | | | 7.0710678118654752 | 7.0710678118654752
|
|
11 | | hello | Sat Jan 02 06:00:00 2010 PST | |
|
|
12 | 10 | hello | Sat Jan 02 06:00:00 2010 PST | |
|
|
(5 rows)
|
|
|
|
CREATE TABLE vfinal_res AS SELECT * FROM vfinal;
|
|
-- overwrite partials with dumped binary values from PostrgeSQL 13 --
|
|
TRUNCATE TABLE t1;
|
|
\COPY t1 FROM data/partialize_finalize_data.csv WITH CSV HEADER
|
|
--repeat query to verify partial serialization sanitization works for versions PG >= 14
|
|
CREATE TABLE vfinal_dump_res AS SELECT * FROM vfinal;
|
|
-- compare results to verify there is no difference
|
|
(SELECT * FROM vfinal_res) EXCEPT (SELECT * FROM vfinal_dump_res);
|
|
a | sumb | minc | maxd | stddevb | stddeve
|
|
---+------+------+------+---------+---------
|
|
(0 rows)
|
|
|
|
--with having clause --
|
|
select a, b , _timescaledb_internal.finalize_agg( 'min(text)', 'pg_catalog', 'default', null, partialc, null::text ) minc, _timescaledb_internal.finalize_agg( 'max(timestamp with time zone)', null, null, null, partiald, null::timestamptz ) maxd from t1 where b is not null group by a, b having _timescaledb_internal.finalize_agg( 'max(timestamp with time zone)', null, null, null, partiald, null::timestamptz ) is not null order by a, b;
|
|
a | b | minc | maxd
|
|
----+----+-------+------------------------------
|
|
1 | 10 | hello | Fri Jan 01 09:00:00 2010 PST
|
|
1 | 20 | abc | Sat Jan 02 09:00:00 2010 PST
|
|
1 | 30 | abcd | Sun Jan 03 09:00:00 2010 PST
|
|
1 | 50 | | Fri Jan 01 09:00:00 2010 PST
|
|
2 | 10 | hello | Fri Jan 01 09:00:00 2010 PST
|
|
2 | 20 | hello | Fri Jan 01 09:00:00 2010 PST
|
|
2 | 30 | hello | Fri Jan 01 09:00:00 2010 PST
|
|
12 | 10 | hello | Sat Jan 02 06:00:00 2010 PST
|
|
(8 rows)
|
|
|
|
--TEST5 test with TOAST data
|
|
drop view vfinal;
|
|
drop table t1;
|
|
drop view v1;
|
|
drop table foo;
|
|
create table foo( a integer, b timestamptz, toastval TEXT);
|
|
-- Set storage type to EXTERNAL to prevent PostgreSQL from compressing my
|
|
-- easily compressable string and instead store it with TOAST
|
|
ALTER TABLE foo ALTER COLUMN toastval SET STORAGE EXTERNAL;
|
|
SELECT count(*) FROM create_hypertable('foo', 'b');
|
|
NOTICE: adding not-null constraint to column "b"
|
|
count
|
|
-------
|
|
1
|
|
(1 row)
|
|
|
|
INSERT INTO foo VALUES( 1, '2004-10-19 10:23:54', repeat('this must be over 2k. ', 1100));
|
|
INSERT INTO foo VALUES(1, '2005-10-19 10:23:54', repeat('I am a tall big giraffe in the zoo. ', 1100));
|
|
INSERT INTO foo values( 1, '2005-01-01 00:00:00+00', NULL);
|
|
INSERT INTO foo values( 2, '2005-01-01 00:00:00+00', NULL);
|
|
create or replace view v1(a, partialb, partialtv) as select a, _timescaledb_internal.partialize_agg( max(b) ), _timescaledb_internal.partialize_agg( min(toastval)) from foo group by a;
|
|
EXPLAIN (VERBOSE, COSTS OFF)
|
|
create table t1 as select * from v1;
|
|
QUERY PLAN
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
Partial HashAggregate
|
|
Output: _hyper_1_1_chunk.a, _timescaledb_internal.partialize_agg(PARTIAL max(_hyper_1_1_chunk.b)), _timescaledb_internal.partialize_agg(PARTIAL min(_hyper_1_1_chunk.toastval))
|
|
Group Key: _hyper_1_1_chunk.a
|
|
-> Append
|
|
-> Seq Scan on _timescaledb_internal._hyper_1_1_chunk
|
|
Output: _hyper_1_1_chunk.a, _hyper_1_1_chunk.b, _hyper_1_1_chunk.toastval
|
|
-> Seq Scan on _timescaledb_internal._hyper_1_2_chunk
|
|
Output: _hyper_1_2_chunk.a, _hyper_1_2_chunk.b, _hyper_1_2_chunk.toastval
|
|
-> Seq Scan on _timescaledb_internal._hyper_1_3_chunk
|
|
Output: _hyper_1_3_chunk.a, _hyper_1_3_chunk.b, _hyper_1_3_chunk.toastval
|
|
(10 rows)
|
|
|
|
create table t1 as select * from v1;
|
|
insert into t1 select * from v1;
|
|
select a, _timescaledb_internal.finalize_agg( 'max(timestamp with time zone)', null, null, null, partialb, null::timestamptz ) maxb,
|
|
_timescaledb_internal.finalize_agg( 'min(text)', 'pg_catalog', 'default', null, partialtv, null::text ) = repeat('I am a tall big giraffe in the zoo. ', 1100) mintv_equal
|
|
from t1 group by a order by a;
|
|
a | maxb | mintv_equal
|
|
---+------------------------------+-------------
|
|
1 | Wed Oct 19 10:23:54 2005 PDT | t
|
|
2 | Fri Dec 31 16:00:00 2004 PST |
|
|
(2 rows)
|
|
|
|
--non top-level partials
|
|
with cte as (
|
|
select a, _timescaledb_internal.partialize_agg(min(toastval)) tp from foo group by a
|
|
)
|
|
select length(tp) from cte;
|
|
length
|
|
--------
|
|
40700
|
|
|
|
(2 rows)
|
|
|
|
select length(_timescaledb_internal.partialize_agg( min(toastval))) from foo group by a;
|
|
length
|
|
--------
|
|
40700
|
|
|
|
(2 rows)
|
|
|
|
select length(_timescaledb_internal.partialize_agg(min(a+1))) from foo;
|
|
length
|
|
--------
|
|
4
|
|
(1 row)
|
|
|
|
\set ON_ERROR_STOP 0
|
|
select length(_timescaledb_internal.partialize_agg(1+min(a))) from foo;
|
|
ERROR: the input to partialize must be an aggregate
|
|
select length(_timescaledb_internal.partialize_agg(min(a)+min(a))) from foo;
|
|
ERROR: the input to partialize must be an aggregate
|
|
--non-trivial HAVING clause not allowed with partialize_agg
|
|
select time_bucket('1 hour', b) as b, _timescaledb_internal.partialize_agg(avg(a))
|
|
from foo
|
|
group by 1
|
|
having avg(a) > 3;
|
|
ERROR: cannot partialize aggregate with HAVING clause
|
|
--mixing partialized and non-partialized aggs is not allowed
|
|
select time_bucket('1 hour', b) as b, _timescaledb_internal.partialize_agg(avg(a)), sum(a)
|
|
from foo
|
|
group by 1;
|
|
ERROR: cannot mix partialized and non-partialized aggregates in the same statement
|
|
\set ON_ERROR_STOP 1
|
|
--partializing works with HAVING when the planner can effectively
|
|
--reduce it. In this case to a simple filter.
|
|
select time_bucket('1 hour', b) as b, toastval, _timescaledb_internal.partialize_agg(avg(a))
|
|
from foo
|
|
group by b, toastval
|
|
having toastval LIKE 'does not exist';
|
|
b | toastval | partialize_agg
|
|
---+----------+----------------
|
|
(0 rows)
|
|
|
|
--
|
|
-- TEST FINALIZEFUNC_EXTRA
|
|
--
|
|
-- create special aggregate to test ffunc_extra
|
|
-- Raise warning with the actual type being passed in
|
|
CREATE OR REPLACE FUNCTION fake_ffunc(a int8, b int, x anyelement)
|
|
RETURNS anyelement AS $$
|
|
BEGIN
|
|
RAISE WARNING 'type %', pg_typeof(x);
|
|
RETURN x;
|
|
END;
|
|
$$
|
|
LANGUAGE plpgsql;
|
|
CREATE OR REPLACE FUNCTION fake_sfunc(a int8, b int, x anyelement)
|
|
RETURNS int8 AS $$
|
|
BEGIN
|
|
RETURN b;
|
|
END; $$
|
|
LANGUAGE plpgsql;
|
|
CREATE AGGREGATE aggregate_to_test_ffunc_extra(int, anyelement) (
|
|
SFUNC = fake_sfunc,
|
|
STYPE = int8,
|
|
COMBINEFUNC = int8pl,
|
|
FINALFUNC = fake_ffunc,
|
|
PARALLEL = SAFE,
|
|
FINALFUNC_EXTRA
|
|
);
|
|
select aggregate_to_test_ffunc_extra(8, 'name'::text);
|
|
WARNING: type text
|
|
aggregate_to_test_ffunc_extra
|
|
-------------------------------
|
|
|
|
(1 row)
|
|
|
|
\set ON_ERROR_STOP 0
|
|
--errors on wrong input type array
|
|
with cte as (SELECT _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
|
|
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, null, part, null::text) from cte;
|
|
ERROR: cannot pass null input_type with FINALFUNC_EXTRA aggregates
|
|
with cte as (SELECT _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
|
|
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['a'::name, 'b'::name, 'c'::name]], part, null::text) from cte;
|
|
ERROR: invalid input type array: expecting slices of size 2
|
|
with cte as (SELECT _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
|
|
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array[]::name[]]::name[], part, null::text) from cte;
|
|
ERROR: invalid input type array: wrong number of dimensions
|
|
with cte as (SELECT _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
|
|
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[]::name[], part, null::text) from cte;
|
|
ERROR: invalid input type array: wrong number of dimensions
|
|
with cte as (SELECT _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
|
|
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['public'::name, 'int'::name], array['public', 'text']], part, null::text) from cte;
|
|
ERROR: invalid input type: public.int
|
|
with cte as (SELECT _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
|
|
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['public'::name, 'int4'::name], array['public', 'text']], part, null::text) from cte;
|
|
ERROR: invalid input type: public.int4
|
|
with cte as (SELECT _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
|
|
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['pg_catalog'::name, 'int4'::name], array['pg_catalog', 'text'], array['pg_catalog', 'text']], part, null::text) from cte;
|
|
ERROR: invalid number of input types
|
|
select _timescaledb_internal.finalize_agg(NULL::text,NULL::name,NULL::name,NULL::_name,NULL::bytea,a) over () from foo;
|
|
ERROR: finalize_agg_sfunc called in non-aggregate context
|
|
\set ON_ERROR_STOP 1
|
|
--make sure right type in warning and is null returns true
|
|
with cte as (SELECT _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
|
|
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['pg_catalog'::name, 'int4'::name], array['pg_catalog', 'text']], part, null::text) is null from cte;
|
|
WARNING: type text
|
|
?column?
|
|
----------
|
|
t
|
|
(1 row)
|
|
|
|
with cte as (SELECT _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 1::bigint)) as part)
|
|
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['pg_catalog'::name, 'int4'::name], array['pg_catalog', 'int8']], part, null::text) is null from cte;
|
|
WARNING: type bigint
|
|
?column?
|
|
----------
|
|
t
|
|
(1 row)
|
|
|
|
-- Issue 4922
|
|
CREATE TABLE issue4922 (
|
|
time TIMESTAMPTZ NOT NULL,
|
|
value INTEGER
|
|
);
|
|
SELECT create_hypertable('issue4922', 'time');
|
|
create_hypertable
|
|
------------------------
|
|
(2,public,issue4922,t)
|
|
(1 row)
|
|
|
|
-- helper function: integer -> pseudorandom integer [0..100].
|
|
CREATE OR REPLACE FUNCTION mix(x INTEGER) RETURNS INTEGER AS $$ SELECT (((hashint4(x) / (pow(2, 31) - 1) + 1) / 2) * 100)::INTEGER $$ LANGUAGE SQL;
|
|
INSERT INTO issue4922 (time, value)
|
|
SELECT '2022-01-01 00:00:00-03'::timestamptz + interval '1 year' * mix(x), mix(x)
|
|
FROM generate_series(1, 100000) x(x);
|
|
SET force_parallel_mode = 'on';
|
|
SET parallel_setup_cost = 0;
|
|
-- Materialize partials from execution of parallel query plan
|
|
EXPLAIN (VERBOSE, COSTS OFF)
|
|
SELECT
|
|
_timescaledb_internal.partialize_agg(sum(value)) AS partial_sum,
|
|
_timescaledb_internal.partialize_agg(avg(value)) AS partial_avg,
|
|
_timescaledb_internal.partialize_agg(min(value)) AS partial_min,
|
|
_timescaledb_internal.partialize_agg(max(value)) AS partial_max,
|
|
_timescaledb_internal.partialize_agg(count(*)) AS partial_count
|
|
FROM public.issue4922;
|
|
QUERY PLAN
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
Partial Aggregate
|
|
Output: _timescaledb_internal.partialize_agg(PARTIAL sum(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL avg(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL min(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL max(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL count(*))
|
|
-> Gather
|
|
Output: (PARTIAL sum(_hyper_2_4_chunk.value)), (PARTIAL avg(_hyper_2_4_chunk.value)), (PARTIAL min(_hyper_2_4_chunk.value)), (PARTIAL max(_hyper_2_4_chunk.value)), (PARTIAL count(*))
|
|
Workers Planned: 2
|
|
-> Partial Aggregate
|
|
Output: PARTIAL sum(_hyper_2_4_chunk.value), PARTIAL avg(_hyper_2_4_chunk.value), PARTIAL min(_hyper_2_4_chunk.value), PARTIAL max(_hyper_2_4_chunk.value), PARTIAL count(*)
|
|
-> Parallel Append
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_4_chunk
|
|
Output: _hyper_2_4_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_5_chunk
|
|
Output: _hyper_2_5_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_6_chunk
|
|
Output: _hyper_2_6_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_7_chunk
|
|
Output: _hyper_2_7_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_8_chunk
|
|
Output: _hyper_2_8_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_9_chunk
|
|
Output: _hyper_2_9_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_10_chunk
|
|
Output: _hyper_2_10_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_11_chunk
|
|
Output: _hyper_2_11_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_12_chunk
|
|
Output: _hyper_2_12_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_13_chunk
|
|
Output: _hyper_2_13_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_14_chunk
|
|
Output: _hyper_2_14_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_15_chunk
|
|
Output: _hyper_2_15_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_16_chunk
|
|
Output: _hyper_2_16_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_17_chunk
|
|
Output: _hyper_2_17_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_18_chunk
|
|
Output: _hyper_2_18_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_19_chunk
|
|
Output: _hyper_2_19_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_20_chunk
|
|
Output: _hyper_2_20_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_21_chunk
|
|
Output: _hyper_2_21_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_22_chunk
|
|
Output: _hyper_2_22_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_23_chunk
|
|
Output: _hyper_2_23_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_24_chunk
|
|
Output: _hyper_2_24_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_25_chunk
|
|
Output: _hyper_2_25_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_26_chunk
|
|
Output: _hyper_2_26_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_27_chunk
|
|
Output: _hyper_2_27_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_28_chunk
|
|
Output: _hyper_2_28_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_29_chunk
|
|
Output: _hyper_2_29_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_30_chunk
|
|
Output: _hyper_2_30_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_31_chunk
|
|
Output: _hyper_2_31_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_32_chunk
|
|
Output: _hyper_2_32_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_33_chunk
|
|
Output: _hyper_2_33_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_34_chunk
|
|
Output: _hyper_2_34_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_35_chunk
|
|
Output: _hyper_2_35_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_36_chunk
|
|
Output: _hyper_2_36_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_37_chunk
|
|
Output: _hyper_2_37_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_38_chunk
|
|
Output: _hyper_2_38_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_39_chunk
|
|
Output: _hyper_2_39_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_40_chunk
|
|
Output: _hyper_2_40_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_41_chunk
|
|
Output: _hyper_2_41_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_42_chunk
|
|
Output: _hyper_2_42_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_43_chunk
|
|
Output: _hyper_2_43_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_44_chunk
|
|
Output: _hyper_2_44_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_45_chunk
|
|
Output: _hyper_2_45_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_46_chunk
|
|
Output: _hyper_2_46_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_47_chunk
|
|
Output: _hyper_2_47_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_48_chunk
|
|
Output: _hyper_2_48_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_49_chunk
|
|
Output: _hyper_2_49_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_50_chunk
|
|
Output: _hyper_2_50_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_51_chunk
|
|
Output: _hyper_2_51_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_52_chunk
|
|
Output: _hyper_2_52_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_53_chunk
|
|
Output: _hyper_2_53_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_54_chunk
|
|
Output: _hyper_2_54_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_55_chunk
|
|
Output: _hyper_2_55_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_56_chunk
|
|
Output: _hyper_2_56_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_57_chunk
|
|
Output: _hyper_2_57_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_58_chunk
|
|
Output: _hyper_2_58_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_59_chunk
|
|
Output: _hyper_2_59_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_60_chunk
|
|
Output: _hyper_2_60_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_61_chunk
|
|
Output: _hyper_2_61_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_62_chunk
|
|
Output: _hyper_2_62_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_63_chunk
|
|
Output: _hyper_2_63_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_64_chunk
|
|
Output: _hyper_2_64_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_65_chunk
|
|
Output: _hyper_2_65_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_66_chunk
|
|
Output: _hyper_2_66_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_67_chunk
|
|
Output: _hyper_2_67_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_68_chunk
|
|
Output: _hyper_2_68_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_69_chunk
|
|
Output: _hyper_2_69_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_70_chunk
|
|
Output: _hyper_2_70_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_71_chunk
|
|
Output: _hyper_2_71_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_72_chunk
|
|
Output: _hyper_2_72_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_73_chunk
|
|
Output: _hyper_2_73_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_74_chunk
|
|
Output: _hyper_2_74_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_75_chunk
|
|
Output: _hyper_2_75_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_76_chunk
|
|
Output: _hyper_2_76_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_77_chunk
|
|
Output: _hyper_2_77_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_78_chunk
|
|
Output: _hyper_2_78_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_79_chunk
|
|
Output: _hyper_2_79_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_80_chunk
|
|
Output: _hyper_2_80_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_81_chunk
|
|
Output: _hyper_2_81_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_82_chunk
|
|
Output: _hyper_2_82_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_83_chunk
|
|
Output: _hyper_2_83_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_84_chunk
|
|
Output: _hyper_2_84_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_85_chunk
|
|
Output: _hyper_2_85_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_86_chunk
|
|
Output: _hyper_2_86_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_87_chunk
|
|
Output: _hyper_2_87_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_88_chunk
|
|
Output: _hyper_2_88_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_89_chunk
|
|
Output: _hyper_2_89_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_90_chunk
|
|
Output: _hyper_2_90_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_91_chunk
|
|
Output: _hyper_2_91_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_92_chunk
|
|
Output: _hyper_2_92_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_93_chunk
|
|
Output: _hyper_2_93_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_94_chunk
|
|
Output: _hyper_2_94_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_95_chunk
|
|
Output: _hyper_2_95_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_96_chunk
|
|
Output: _hyper_2_96_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_97_chunk
|
|
Output: _hyper_2_97_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_98_chunk
|
|
Output: _hyper_2_98_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_99_chunk
|
|
Output: _hyper_2_99_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_100_chunk
|
|
Output: _hyper_2_100_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_101_chunk
|
|
Output: _hyper_2_101_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_102_chunk
|
|
Output: _hyper_2_102_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_103_chunk
|
|
Output: _hyper_2_103_chunk.value
|
|
-> Parallel Seq Scan on _timescaledb_internal._hyper_2_104_chunk
|
|
Output: _hyper_2_104_chunk.value
|
|
(210 rows)
|
|
|
|
CREATE MATERIALIZED VIEW issue4922_partials_parallel AS
|
|
SELECT
|
|
_timescaledb_internal.partialize_agg(sum(value)) AS partial_sum,
|
|
_timescaledb_internal.partialize_agg(avg(value)) AS partial_avg,
|
|
_timescaledb_internal.partialize_agg(min(value)) AS partial_min,
|
|
_timescaledb_internal.partialize_agg(max(value)) AS partial_max,
|
|
_timescaledb_internal.partialize_agg(count(*)) AS partial_count
|
|
FROM public.issue4922;
|
|
-- Materialize partials from execution of non-parallel query plan
|
|
SET max_parallel_workers_per_gather = 0;
|
|
EXPLAIN (VERBOSE, COSTS OFF)
|
|
SELECT
|
|
_timescaledb_internal.partialize_agg(sum(value)) AS partial_sum,
|
|
_timescaledb_internal.partialize_agg(avg(value)) AS partial_avg,
|
|
_timescaledb_internal.partialize_agg(min(value)) AS partial_min,
|
|
_timescaledb_internal.partialize_agg(max(value)) AS partial_max,
|
|
_timescaledb_internal.partialize_agg(count(*)) AS partial_count
|
|
FROM public.issue4922;
|
|
QUERY PLAN
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
Partial Aggregate
|
|
Output: _timescaledb_internal.partialize_agg(PARTIAL sum(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL avg(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL min(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL max(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL count(*))
|
|
-> Append
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_4_chunk
|
|
Output: _hyper_2_4_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_5_chunk
|
|
Output: _hyper_2_5_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_6_chunk
|
|
Output: _hyper_2_6_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_7_chunk
|
|
Output: _hyper_2_7_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_8_chunk
|
|
Output: _hyper_2_8_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_9_chunk
|
|
Output: _hyper_2_9_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_10_chunk
|
|
Output: _hyper_2_10_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_11_chunk
|
|
Output: _hyper_2_11_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_12_chunk
|
|
Output: _hyper_2_12_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_13_chunk
|
|
Output: _hyper_2_13_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_14_chunk
|
|
Output: _hyper_2_14_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_15_chunk
|
|
Output: _hyper_2_15_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_16_chunk
|
|
Output: _hyper_2_16_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_17_chunk
|
|
Output: _hyper_2_17_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_18_chunk
|
|
Output: _hyper_2_18_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_19_chunk
|
|
Output: _hyper_2_19_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_20_chunk
|
|
Output: _hyper_2_20_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_21_chunk
|
|
Output: _hyper_2_21_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_22_chunk
|
|
Output: _hyper_2_22_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_23_chunk
|
|
Output: _hyper_2_23_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_24_chunk
|
|
Output: _hyper_2_24_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_25_chunk
|
|
Output: _hyper_2_25_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_26_chunk
|
|
Output: _hyper_2_26_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_27_chunk
|
|
Output: _hyper_2_27_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_28_chunk
|
|
Output: _hyper_2_28_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_29_chunk
|
|
Output: _hyper_2_29_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_30_chunk
|
|
Output: _hyper_2_30_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_31_chunk
|
|
Output: _hyper_2_31_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_32_chunk
|
|
Output: _hyper_2_32_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_33_chunk
|
|
Output: _hyper_2_33_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_34_chunk
|
|
Output: _hyper_2_34_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_35_chunk
|
|
Output: _hyper_2_35_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_36_chunk
|
|
Output: _hyper_2_36_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_37_chunk
|
|
Output: _hyper_2_37_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_38_chunk
|
|
Output: _hyper_2_38_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_39_chunk
|
|
Output: _hyper_2_39_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_40_chunk
|
|
Output: _hyper_2_40_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_41_chunk
|
|
Output: _hyper_2_41_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_42_chunk
|
|
Output: _hyper_2_42_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_43_chunk
|
|
Output: _hyper_2_43_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_44_chunk
|
|
Output: _hyper_2_44_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_45_chunk
|
|
Output: _hyper_2_45_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_46_chunk
|
|
Output: _hyper_2_46_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_47_chunk
|
|
Output: _hyper_2_47_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_48_chunk
|
|
Output: _hyper_2_48_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_49_chunk
|
|
Output: _hyper_2_49_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_50_chunk
|
|
Output: _hyper_2_50_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_51_chunk
|
|
Output: _hyper_2_51_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_52_chunk
|
|
Output: _hyper_2_52_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_53_chunk
|
|
Output: _hyper_2_53_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_54_chunk
|
|
Output: _hyper_2_54_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_55_chunk
|
|
Output: _hyper_2_55_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_56_chunk
|
|
Output: _hyper_2_56_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_57_chunk
|
|
Output: _hyper_2_57_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_58_chunk
|
|
Output: _hyper_2_58_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_59_chunk
|
|
Output: _hyper_2_59_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_60_chunk
|
|
Output: _hyper_2_60_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_61_chunk
|
|
Output: _hyper_2_61_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_62_chunk
|
|
Output: _hyper_2_62_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_63_chunk
|
|
Output: _hyper_2_63_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_64_chunk
|
|
Output: _hyper_2_64_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_65_chunk
|
|
Output: _hyper_2_65_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_66_chunk
|
|
Output: _hyper_2_66_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_67_chunk
|
|
Output: _hyper_2_67_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_68_chunk
|
|
Output: _hyper_2_68_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_69_chunk
|
|
Output: _hyper_2_69_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_70_chunk
|
|
Output: _hyper_2_70_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_71_chunk
|
|
Output: _hyper_2_71_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_72_chunk
|
|
Output: _hyper_2_72_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_73_chunk
|
|
Output: _hyper_2_73_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_74_chunk
|
|
Output: _hyper_2_74_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_75_chunk
|
|
Output: _hyper_2_75_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_76_chunk
|
|
Output: _hyper_2_76_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_77_chunk
|
|
Output: _hyper_2_77_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_78_chunk
|
|
Output: _hyper_2_78_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_79_chunk
|
|
Output: _hyper_2_79_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_80_chunk
|
|
Output: _hyper_2_80_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_81_chunk
|
|
Output: _hyper_2_81_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_82_chunk
|
|
Output: _hyper_2_82_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_83_chunk
|
|
Output: _hyper_2_83_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_84_chunk
|
|
Output: _hyper_2_84_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_85_chunk
|
|
Output: _hyper_2_85_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_86_chunk
|
|
Output: _hyper_2_86_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_87_chunk
|
|
Output: _hyper_2_87_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_88_chunk
|
|
Output: _hyper_2_88_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_89_chunk
|
|
Output: _hyper_2_89_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_90_chunk
|
|
Output: _hyper_2_90_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_91_chunk
|
|
Output: _hyper_2_91_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_92_chunk
|
|
Output: _hyper_2_92_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_93_chunk
|
|
Output: _hyper_2_93_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_94_chunk
|
|
Output: _hyper_2_94_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_95_chunk
|
|
Output: _hyper_2_95_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_96_chunk
|
|
Output: _hyper_2_96_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_97_chunk
|
|
Output: _hyper_2_97_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_98_chunk
|
|
Output: _hyper_2_98_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_99_chunk
|
|
Output: _hyper_2_99_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_100_chunk
|
|
Output: _hyper_2_100_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_101_chunk
|
|
Output: _hyper_2_101_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_102_chunk
|
|
Output: _hyper_2_102_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_103_chunk
|
|
Output: _hyper_2_103_chunk.value
|
|
-> Seq Scan on _timescaledb_internal._hyper_2_104_chunk
|
|
Output: _hyper_2_104_chunk.value
|
|
(205 rows)
|
|
|
|
CREATE MATERIALIZED VIEW issue4922_partials_non_parallel AS
|
|
SELECT
|
|
_timescaledb_internal.partialize_agg(sum(value)) AS partial_sum,
|
|
_timescaledb_internal.partialize_agg(avg(value)) AS partial_avg,
|
|
_timescaledb_internal.partialize_agg(min(value)) AS partial_min,
|
|
_timescaledb_internal.partialize_agg(max(value)) AS partial_max,
|
|
_timescaledb_internal.partialize_agg(count(*)) AS partial_count
|
|
FROM public.issue4922;
|
|
RESET max_parallel_workers_per_gather;
|
|
-- partials should be the same in both parallel and non-parallel execution
|
|
SELECT * FROM issue4922_partials_parallel;
|
|
partial_sum | partial_avg | partial_min | partial_max | partial_count
|
|
--------------------+--------------------------------------------------------------------------------------------+-------------+-------------+--------------------
|
|
\x00000000004c4fa9 | \x00000001000000000000001400000002000000010000000800000000000186a00000000800000000004c4fa9 | \x00000000 | \x00000064 | \x00000000000186a0
|
|
(1 row)
|
|
|
|
SELECT * FROM issue4922_partials_non_parallel;
|
|
partial_sum | partial_avg | partial_min | partial_max | partial_count
|
|
--------------------+--------------------------------------------------------------------------------------------+-------------+-------------+--------------------
|
|
\x00000000004c4fa9 | \x00000001000000000000001400000002000000010000000800000000000186a00000000800000000004c4fa9 | \x00000000 | \x00000064 | \x00000000000186a0
|
|
(1 row)
|
|
|
|
-- Compare results from partial and non-partial query execution
|
|
SELECT
|
|
sum(value),
|
|
avg(value),
|
|
min(value),
|
|
max(value),
|
|
count(*)
|
|
FROM issue4922;
|
|
sum | avg | min | max | count
|
|
---------+---------------------+-----+-----+--------
|
|
5001129 | 50.0112900000000000 | 0 | 100 | 100000
|
|
(1 row)
|
|
|
|
-- The results should be the EQUAL TO the previous query
|
|
SELECT
|
|
_timescaledb_internal.finalize_agg('pg_catalog.sum(integer)'::text, NULL::name, NULL::name, '{{pg_catalog,int4}}'::name[], partial_sum, NULL::bigint) AS sum,
|
|
_timescaledb_internal.finalize_agg('pg_catalog.avg(integer)'::text, NULL::name, NULL::name, '{{pg_catalog,int4}}'::name[], partial_avg, NULL::numeric) AS avg,
|
|
_timescaledb_internal.finalize_agg('pg_catalog.min(integer)'::text, NULL::name, NULL::name, '{{pg_catalog,int4}}'::name[], partial_min, NULL::integer) AS min,
|
|
_timescaledb_internal.finalize_agg('pg_catalog.max(integer)'::text, NULL::name, NULL::name, '{{pg_catalog,int4}}'::name[], partial_max, NULL::integer) AS max,
|
|
_timescaledb_internal.finalize_agg('pg_catalog.count()'::text, NULL::name, NULL::name, '{}'::name[], partial_count, NULL::bigint) AS count
|
|
FROM issue4922_partials_parallel;
|
|
sum | avg | min | max | count
|
|
---------+---------------------+-----+-----+--------
|
|
5001129 | 50.0112900000000000 | 0 | 100 | 100000
|
|
(1 row)
|
|
|