From 0ceb38959cd152ace83b8a40b9312a7233f3533a Mon Sep 17 00:00:00 2001 From: Jan Nidzwetzki Date: Tue, 12 Sep 2023 11:21:56 +0200 Subject: [PATCH] Don't build partition info for local hypertables So far, we have created fake partitioning info for hypertables if the PostgreSQL setting 'enable_partitionwise_aggregate' is set. This causes PostgreSQL to push down partial aggregations to the chunk level. However, the PostgreSQL code has some drawbacks because the query is replanned and optimizations like ChunkAppend are lost. Since #5596 we have implemented our own code to push down partial aggregations. Therefore, we can ignore the PostgreSQL setting from now on. --- src/planner/expand_hypertable.c | 6 +- test/expected/partitionwise.out | 325 ++++++++------------------------ test/sql/partitionwise.sql | 48 +---- 3 files changed, 88 insertions(+), 291 deletions(-) diff --git a/src/planner/expand_hypertable.c b/src/planner/expand_hypertable.c index af897c594a7..bffc60068b2 100644 --- a/src/planner/expand_hypertable.c +++ b/src/planner/expand_hypertable.c @@ -1381,10 +1381,8 @@ ts_plan_expand_hypertable_chunks(Hypertable *ht, PlannerInfo *root, RelOptInfo * /* Adding partition info will make PostgreSQL consider the inheritance * children as part of a partitioned relation. This will enable - * partitionwise aggregation. */ - if ((enable_partitionwise_aggregate && - !has_partialize_function((Node *) root->parse->targetList, TS_DO_NOT_FIX_AGGSPLIT)) || - hypertable_is_distributed(ht)) + * partitionwise aggregation for distributed queries. */ + if (hypertable_is_distributed(ht)) { build_hypertable_partition_info(ht, root, rel, list_length(inh_oids)); } diff --git a/test/expected/partitionwise.out b/test/expected/partitionwise.out index 1ebfaecc3e5..4a86a02de37 100644 --- a/test/expected/partitionwise.out +++ b/test/expected/partitionwise.out @@ -308,44 +308,32 @@ ORDER BY 1, 2; -- Now run on hypertable -- All partition keys not covered by GROUP BY (partial partitionwise) -SET enable_partitionwise_aggregate = 'off'; +SET timescaledb.enable_chunkwise_aggregation = 'off'; :PREFIX SELECT device, avg(temp) FROM hyper GROUP BY 1 ORDER BY 1; - QUERY PLAN ------------------------------------------------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------------- Sort Output: _hyper_1_1_chunk.device, (avg(_hyper_1_1_chunk.temp)) Sort Key: _hyper_1_1_chunk.device - -> Finalize HashAggregate + -> HashAggregate Output: _hyper_1_1_chunk.device, avg(_hyper_1_1_chunk.temp) Group Key: _hyper_1_1_chunk.device -> Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk.device, PARTIAL avg(_hyper_1_1_chunk.temp) - Group Key: _hyper_1_1_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk - Output: _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp - -> Partial HashAggregate - Output: _hyper_1_2_chunk.device, PARTIAL avg(_hyper_1_2_chunk.temp) - Group Key: _hyper_1_2_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk - Output: _hyper_1_2_chunk.device, _hyper_1_2_chunk.temp - -> Partial HashAggregate - Output: _hyper_1_3_chunk.device, PARTIAL avg(_hyper_1_3_chunk.temp) - Group Key: _hyper_1_3_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_3_chunk - Output: _hyper_1_3_chunk.device, _hyper_1_3_chunk.temp - -> Partial HashAggregate - Output: _hyper_1_4_chunk.device, PARTIAL avg(_hyper_1_4_chunk.temp) - Group Key: _hyper_1_4_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk - Output: _hyper_1_4_chunk.device, _hyper_1_4_chunk.temp -(27 rows) + -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp + -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk.device, _hyper_1_2_chunk.temp + -> Seq Scan on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk.device, _hyper_1_3_chunk.temp + -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk.device, _hyper_1_4_chunk.temp +(15 rows) -SET enable_partitionwise_aggregate = 'on'; +SET timescaledb.enable_chunkwise_aggregation = 'on'; :PREFIX SELECT device, avg(temp) FROM hyper @@ -383,7 +371,32 @@ ORDER BY 1; (27 rows) -- All partition keys covered (full partitionwise) -SET enable_partitionwise_aggregate = 'off'; +SET timescaledb.enable_chunkwise_aggregation = 'off'; +:PREFIX +SELECT time, device, avg(temp) +FROM hyper +GROUP BY 1, 2 +ORDER BY 1, 2; + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Sort + Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, (avg(_hyper_1_1_chunk.temp)) + Sort Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device + -> HashAggregate + Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, avg(_hyper_1_1_chunk.temp) + Group Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device + -> Append + -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp + -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk."time", _hyper_1_2_chunk.device, _hyper_1_2_chunk.temp + -> Seq Scan on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk."time", _hyper_1_3_chunk.device, _hyper_1_3_chunk.temp + -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."time", _hyper_1_4_chunk.device, _hyper_1_4_chunk.temp +(15 rows) + +SET timescaledb.enable_chunkwise_aggregation = 'on'; :PREFIX SELECT time, device, avg(temp) FROM hyper @@ -440,60 +453,23 @@ ORDER BY 1, 2; Output: _hyper_1_4_chunk."time", _hyper_1_4_chunk.device, _hyper_1_4_chunk.temp (47 rows) -SET enable_partitionwise_aggregate = 'on'; -:PREFIX -SELECT time, device, avg(temp) -FROM hyper -GROUP BY 1, 2 -ORDER BY 1, 2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------- - Sort - Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, (avg(_hyper_1_1_chunk.temp)) - Sort Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device - -> Finalize HashAggregate - Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, avg(_hyper_1_1_chunk.temp) - Group Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device - -> Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, PARTIAL avg(_hyper_1_1_chunk.temp) - Group Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk - Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp - -> Partial HashAggregate - Output: _hyper_1_2_chunk."time", _hyper_1_2_chunk.device, PARTIAL avg(_hyper_1_2_chunk.temp) - Group Key: _hyper_1_2_chunk."time", _hyper_1_2_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk - Output: _hyper_1_2_chunk."time", _hyper_1_2_chunk.device, _hyper_1_2_chunk.temp - -> Partial HashAggregate - Output: _hyper_1_3_chunk."time", _hyper_1_3_chunk.device, PARTIAL avg(_hyper_1_3_chunk.temp) - Group Key: _hyper_1_3_chunk."time", _hyper_1_3_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_3_chunk - Output: _hyper_1_3_chunk."time", _hyper_1_3_chunk.device, _hyper_1_3_chunk.temp - -> Partial HashAggregate - Output: _hyper_1_4_chunk."time", _hyper_1_4_chunk.device, PARTIAL avg(_hyper_1_4_chunk.temp) - Group Key: _hyper_1_4_chunk."time", _hyper_1_4_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk - Output: _hyper_1_4_chunk."time", _hyper_1_4_chunk.device, _hyper_1_4_chunk.temp -(27 rows) - --- Partial aggregation since date_trunc(time) is not a partition key -SET enable_partitionwise_aggregate = 'off'; +-- Also test time_bucket +SET timescaledb.enable_chunkwise_aggregation = 'off'; :PREFIX -SELECT date_trunc('month', time), device, avg(temp) +SELECT time_bucket('1 month', time), device, avg(temp) FROM hyper GROUP BY 1, 2 ORDER BY 1, 2; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- Sort - Output: (date_trunc('month'::text, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, (avg(_hyper_1_1_chunk.temp)) - Sort Key: (date_trunc('month'::text, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device + Output: (time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, (avg(_hyper_1_1_chunk.temp)) + Sort Key: (time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device -> HashAggregate - Output: (date_trunc('month'::text, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, avg(_hyper_1_1_chunk.temp) - Group Key: date_trunc('month'::text, _hyper_1_1_chunk."time"), _hyper_1_1_chunk.device + Output: (time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, avg(_hyper_1_1_chunk.temp) + Group Key: time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time"), _hyper_1_1_chunk.device -> Result - Output: date_trunc('month'::text, _hyper_1_1_chunk."time"), _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp + Output: time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time"), _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp -> Append -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp @@ -505,45 +481,7 @@ ORDER BY 1, 2; Output: _hyper_1_4_chunk."time", _hyper_1_4_chunk.device, _hyper_1_4_chunk.temp (17 rows) -SET enable_partitionwise_aggregate = 'on'; -:PREFIX -SELECT date_trunc('month', time), device, avg(temp) -FROM hyper -GROUP BY 1, 2 -ORDER BY 1, 2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------ - Sort - Output: (date_trunc('month'::text, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, (avg(_hyper_1_1_chunk.temp)) - Sort Key: (date_trunc('month'::text, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device - -> Finalize HashAggregate - Output: (date_trunc('month'::text, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, avg(_hyper_1_1_chunk.temp) - Group Key: (date_trunc('month'::text, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device - -> Append - -> Partial HashAggregate - Output: (date_trunc('month'::text, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, PARTIAL avg(_hyper_1_1_chunk.temp) - Group Key: date_trunc('month'::text, _hyper_1_1_chunk."time"), _hyper_1_1_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk - Output: date_trunc('month'::text, _hyper_1_1_chunk."time"), _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp - -> Partial HashAggregate - Output: (date_trunc('month'::text, _hyper_1_2_chunk."time")), _hyper_1_2_chunk.device, PARTIAL avg(_hyper_1_2_chunk.temp) - Group Key: date_trunc('month'::text, _hyper_1_2_chunk."time"), _hyper_1_2_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk - Output: date_trunc('month'::text, _hyper_1_2_chunk."time"), _hyper_1_2_chunk.device, _hyper_1_2_chunk.temp - -> Partial HashAggregate - Output: (date_trunc('month'::text, _hyper_1_3_chunk."time")), _hyper_1_3_chunk.device, PARTIAL avg(_hyper_1_3_chunk.temp) - Group Key: date_trunc('month'::text, _hyper_1_3_chunk."time"), _hyper_1_3_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_3_chunk - Output: date_trunc('month'::text, _hyper_1_3_chunk."time"), _hyper_1_3_chunk.device, _hyper_1_3_chunk.temp - -> Partial HashAggregate - Output: (date_trunc('month'::text, _hyper_1_4_chunk."time")), _hyper_1_4_chunk.device, PARTIAL avg(_hyper_1_4_chunk.temp) - Group Key: date_trunc('month'::text, _hyper_1_4_chunk."time"), _hyper_1_4_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk - Output: date_trunc('month'::text, _hyper_1_4_chunk."time"), _hyper_1_4_chunk.device, _hyper_1_4_chunk.temp -(27 rows) - --- Also test time_bucket -SET enable_partitionwise_aggregate = 'off'; +SET timescaledb.enable_chunkwise_aggregation = 'on'; :PREFIX SELECT time_bucket('1 month', time), device, avg(temp) FROM hyper @@ -570,43 +508,6 @@ ORDER BY 1, 2; Output: _hyper_1_4_chunk."time", _hyper_1_4_chunk.device, _hyper_1_4_chunk.temp (17 rows) -SET enable_partitionwise_aggregate = 'on'; -:PREFIX -SELECT time_bucket('1 month', time), device, avg(temp) -FROM hyper -GROUP BY 1, 2 -ORDER BY 1, 2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: (time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, (avg(_hyper_1_1_chunk.temp)) - Sort Key: (time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device - -> Finalize HashAggregate - Output: (time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, avg(_hyper_1_1_chunk.temp) - Group Key: (time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device - -> Append - -> Partial HashAggregate - Output: (time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device, PARTIAL avg(_hyper_1_1_chunk.temp) - Group Key: time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time"), _hyper_1_1_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk - Output: time_bucket('@ 1 mon'::interval, _hyper_1_1_chunk."time"), _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp - -> Partial HashAggregate - Output: (time_bucket('@ 1 mon'::interval, _hyper_1_2_chunk."time")), _hyper_1_2_chunk.device, PARTIAL avg(_hyper_1_2_chunk.temp) - Group Key: time_bucket('@ 1 mon'::interval, _hyper_1_2_chunk."time"), _hyper_1_2_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk - Output: time_bucket('@ 1 mon'::interval, _hyper_1_2_chunk."time"), _hyper_1_2_chunk.device, _hyper_1_2_chunk.temp - -> Partial HashAggregate - Output: (time_bucket('@ 1 mon'::interval, _hyper_1_3_chunk."time")), _hyper_1_3_chunk.device, PARTIAL avg(_hyper_1_3_chunk.temp) - Group Key: time_bucket('@ 1 mon'::interval, _hyper_1_3_chunk."time"), _hyper_1_3_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_3_chunk - Output: time_bucket('@ 1 mon'::interval, _hyper_1_3_chunk."time"), _hyper_1_3_chunk.device, _hyper_1_3_chunk.temp - -> Partial HashAggregate - Output: (time_bucket('@ 1 mon'::interval, _hyper_1_4_chunk."time")), _hyper_1_4_chunk.device, PARTIAL avg(_hyper_1_4_chunk.temp) - Group Key: time_bucket('@ 1 mon'::interval, _hyper_1_4_chunk."time"), _hyper_1_4_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk - Output: time_bucket('@ 1 mon'::interval, _hyper_1_4_chunk."time"), _hyper_1_4_chunk.device, _hyper_1_4_chunk.temp -(27 rows) - -- Test partitionwise joins, mostly to see that we do not break -- anything CREATE TABLE hyper_meta (time timestamptz, device int, info text); @@ -783,35 +684,29 @@ INSERT INTO hyper_timepart SELECT x, ceil(random() * 8), random() * 20 FROM generate_series(0,5000-1) AS x; -- All partition keys covered (full partitionwise) -SET enable_partitionwise_aggregate = 'off'; +SET timescaledb.enable_chunkwise_aggregation = 'off'; :PREFIX SELECT time, device, avg(temp) FROM hyper_timepart GROUP BY 1, 2 ORDER BY 1, 2 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------- Limit Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, (avg(_hyper_3_7_chunk.temp)) -> Sort Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, (avg(_hyper_3_7_chunk.temp)) Sort Key: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device - -> Finalize HashAggregate + -> HashAggregate Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, avg(_hyper_3_7_chunk.temp) Group Key: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device -> Append - -> Partial HashAggregate - Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, PARTIAL avg(_hyper_3_7_chunk.temp) - Group Key: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_3_7_chunk - Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, _hyper_3_7_chunk.temp - -> Partial HashAggregate - Output: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device, PARTIAL avg(_hyper_3_8_chunk.temp) - Group Key: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_3_8_chunk - Output: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device, _hyper_3_8_chunk.temp -(19 rows) + -> Seq Scan on _timescaledb_internal._hyper_3_7_chunk + Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, _hyper_3_7_chunk.temp + -> Seq Scan on _timescaledb_internal._hyper_3_8_chunk + Output: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device, _hyper_3_8_chunk.temp +(13 rows) :PREFIX SELECT time_func(time), device, avg(temp) @@ -841,97 +736,33 @@ LIMIT 10; (17 rows) -- Grouping on original time column should be pushed-down -SET enable_partitionwise_aggregate = 'on'; +SET timescaledb.enable_chunkwise_aggregation = 'on'; :PREFIX SELECT time, device, avg(temp) FROM hyper_timepart GROUP BY 1, 2 ORDER BY 1, 2 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ Limit Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, (avg(_hyper_3_7_chunk.temp)) -> Sort Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, (avg(_hyper_3_7_chunk.temp)) Sort Key: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device - -> Append - -> HashAggregate - Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, avg(_hyper_3_7_chunk.temp) - Group Key: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_3_7_chunk - Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, _hyper_3_7_chunk.temp - -> HashAggregate - Output: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device, avg(_hyper_3_8_chunk.temp) - Group Key: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device - -> Seq Scan on _timescaledb_internal._hyper_3_8_chunk - Output: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device, _hyper_3_8_chunk.temp -(16 rows) - --- Applying the time partitioning function should also allow push-down --- on open dimensions -:PREFIX -SELECT time_func(time), device, avg(temp) -FROM hyper_timepart -GROUP BY 1, 2 -ORDER BY 1, 2 -LIMIT 10; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_func(_hyper_3_7_chunk."time")), _hyper_3_7_chunk.device, (avg(_hyper_3_7_chunk.temp)) - -> Merge Append - Sort Key: (time_func(_hyper_3_7_chunk."time")), _hyper_3_7_chunk.device - -> GroupAggregate - Output: (time_func(_hyper_3_7_chunk."time")), _hyper_3_7_chunk.device, avg(_hyper_3_7_chunk.temp) - Group Key: (time_func(_hyper_3_7_chunk."time")), _hyper_3_7_chunk.device - -> Incremental Sort - Output: (time_func(_hyper_3_7_chunk."time")), _hyper_3_7_chunk.device, _hyper_3_7_chunk.temp - Sort Key: (time_func(_hyper_3_7_chunk."time")), _hyper_3_7_chunk.device - Presorted Key: (time_func(_hyper_3_7_chunk."time")) - -> Index Scan Backward using _hyper_3_7_chunk_hyper_timepart_expr_idx on _timescaledb_internal._hyper_3_7_chunk - Output: time_func(_hyper_3_7_chunk."time"), _hyper_3_7_chunk.device, _hyper_3_7_chunk.temp - -> GroupAggregate - Output: (time_func(_hyper_3_8_chunk."time")), _hyper_3_8_chunk.device, avg(_hyper_3_8_chunk.temp) - Group Key: (time_func(_hyper_3_8_chunk."time")), _hyper_3_8_chunk.device - -> Incremental Sort - Output: (time_func(_hyper_3_8_chunk."time")), _hyper_3_8_chunk.device, _hyper_3_8_chunk.temp - Sort Key: (time_func(_hyper_3_8_chunk."time")), _hyper_3_8_chunk.device - Presorted Key: (time_func(_hyper_3_8_chunk."time")) - -> Index Scan Backward using _hyper_3_8_chunk_hyper_timepart_expr_idx on _timescaledb_internal._hyper_3_8_chunk - Output: time_func(_hyper_3_8_chunk."time"), _hyper_3_8_chunk.device, _hyper_3_8_chunk.temp -(22 rows) - --- Should also work to use partitioning function on closed dimensions -:PREFIX -SELECT time_func(time), _timescaledb_functions.get_partition_hash(device), avg(temp) -FROM hyper_timepart -GROUP BY 1, 2 -ORDER BY 1, 2 -LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: (time_func(_hyper_3_7_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_7_chunk.device)), (avg(_hyper_3_7_chunk.temp)) - -> Merge Append - Sort Key: (time_func(_hyper_3_7_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_7_chunk.device)) - -> GroupAggregate - Output: (time_func(_hyper_3_7_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_7_chunk.device)), avg(_hyper_3_7_chunk.temp) - Group Key: (time_func(_hyper_3_7_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_7_chunk.device)) - -> Incremental Sort - Output: (time_func(_hyper_3_7_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_7_chunk.device)), _hyper_3_7_chunk.temp - Sort Key: (time_func(_hyper_3_7_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_7_chunk.device)) - Presorted Key: (time_func(_hyper_3_7_chunk."time")) - -> Index Scan Backward using _hyper_3_7_chunk_hyper_timepart_expr_idx on _timescaledb_internal._hyper_3_7_chunk - Output: time_func(_hyper_3_7_chunk."time"), _timescaledb_functions.get_partition_hash(_hyper_3_7_chunk.device), _hyper_3_7_chunk.temp - -> GroupAggregate - Output: (time_func(_hyper_3_8_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_8_chunk.device)), avg(_hyper_3_8_chunk.temp) - Group Key: (time_func(_hyper_3_8_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_8_chunk.device)) - -> Incremental Sort - Output: (time_func(_hyper_3_8_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_8_chunk.device)), _hyper_3_8_chunk.temp - Sort Key: (time_func(_hyper_3_8_chunk."time")), (_timescaledb_functions.get_partition_hash(_hyper_3_8_chunk.device)) - Presorted Key: (time_func(_hyper_3_8_chunk."time")) - -> Index Scan Backward using _hyper_3_8_chunk_hyper_timepart_expr_idx on _timescaledb_internal._hyper_3_8_chunk - Output: time_func(_hyper_3_8_chunk."time"), _timescaledb_functions.get_partition_hash(_hyper_3_8_chunk.device), _hyper_3_8_chunk.temp -(22 rows) + -> Finalize HashAggregate + Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, avg(_hyper_3_7_chunk.temp) + Group Key: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device + -> Append + -> Partial HashAggregate + Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, PARTIAL avg(_hyper_3_7_chunk.temp) + Group Key: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device + -> Seq Scan on _timescaledb_internal._hyper_3_7_chunk + Output: _hyper_3_7_chunk."time", _hyper_3_7_chunk.device, _hyper_3_7_chunk.temp + -> Partial HashAggregate + Output: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device, PARTIAL avg(_hyper_3_8_chunk.temp) + Group Key: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device + -> Seq Scan on _timescaledb_internal._hyper_3_8_chunk + Output: _hyper_3_8_chunk."time", _hyper_3_8_chunk.device, _hyper_3_8_chunk.temp +(19 rows) diff --git a/test/sql/partitionwise.sql b/test/sql/partitionwise.sql index f2f7981c439..d341a07befc 100644 --- a/test/sql/partitionwise.sql +++ b/test/sql/partitionwise.sql @@ -115,14 +115,14 @@ ORDER BY 1, 2; -- Now run on hypertable -- All partition keys not covered by GROUP BY (partial partitionwise) -SET enable_partitionwise_aggregate = 'off'; +SET timescaledb.enable_chunkwise_aggregation = 'off'; :PREFIX SELECT device, avg(temp) FROM hyper GROUP BY 1 ORDER BY 1; -SET enable_partitionwise_aggregate = 'on'; +SET timescaledb.enable_chunkwise_aggregation = 'on'; :PREFIX SELECT device, avg(temp) FROM hyper @@ -130,44 +130,29 @@ GROUP BY 1 ORDER BY 1; -- All partition keys covered (full partitionwise) -SET enable_partitionwise_aggregate = 'off'; +SET timescaledb.enable_chunkwise_aggregation = 'off'; :PREFIX SELECT time, device, avg(temp) FROM hyper GROUP BY 1, 2 ORDER BY 1, 2; -SET enable_partitionwise_aggregate = 'on'; +SET timescaledb.enable_chunkwise_aggregation = 'on'; :PREFIX SELECT time, device, avg(temp) FROM hyper GROUP BY 1, 2 ORDER BY 1, 2; --- Partial aggregation since date_trunc(time) is not a partition key -SET enable_partitionwise_aggregate = 'off'; -:PREFIX -SELECT date_trunc('month', time), device, avg(temp) -FROM hyper -GROUP BY 1, 2 -ORDER BY 1, 2; - -SET enable_partitionwise_aggregate = 'on'; -:PREFIX -SELECT date_trunc('month', time), device, avg(temp) -FROM hyper -GROUP BY 1, 2 -ORDER BY 1, 2; - -- Also test time_bucket -SET enable_partitionwise_aggregate = 'off'; +SET timescaledb.enable_chunkwise_aggregation = 'off'; :PREFIX SELECT time_bucket('1 month', time), device, avg(temp) FROM hyper GROUP BY 1, 2 ORDER BY 1, 2; -SET enable_partitionwise_aggregate = 'on'; +SET timescaledb.enable_chunkwise_aggregation = 'on'; :PREFIX SELECT time_bucket('1 month', time), device, avg(temp) FROM hyper @@ -230,7 +215,7 @@ SELECT x, ceil(random() * 8), random() * 20 FROM generate_series(0,5000-1) AS x; -- All partition keys covered (full partitionwise) -SET enable_partitionwise_aggregate = 'off'; +SET timescaledb.enable_chunkwise_aggregation = 'off'; :PREFIX SELECT time, device, avg(temp) FROM hyper_timepart @@ -246,27 +231,10 @@ ORDER BY 1, 2 LIMIT 10; -- Grouping on original time column should be pushed-down -SET enable_partitionwise_aggregate = 'on'; +SET timescaledb.enable_chunkwise_aggregation = 'on'; :PREFIX SELECT time, device, avg(temp) FROM hyper_timepart GROUP BY 1, 2 ORDER BY 1, 2 LIMIT 10; - --- Applying the time partitioning function should also allow push-down --- on open dimensions -:PREFIX -SELECT time_func(time), device, avg(temp) -FROM hyper_timepart -GROUP BY 1, 2 -ORDER BY 1, 2 -LIMIT 10; - --- Should also work to use partitioning function on closed dimensions -:PREFIX -SELECT time_func(time), _timescaledb_functions.get_partition_hash(device), avg(temp) -FROM hyper_timepart -GROUP BY 1, 2 -ORDER BY 1, 2 -LIMIT 10;