Simplify setting chunk_time_interval for caggs

This patch allows setting chunk_time_interval when creating
a continuous agg and allows changing it with ALTER MATERIALIZED
VIEW. Previously you had to create the cagg with `WITH NO DATA`
and then call `set_chunk_time_interval` followed by manually
refreshing.
This commit is contained in:
Sven Klemm 2025-03-14 00:08:16 +01:00
parent 2b933696ec
commit 4bd2201c54
No known key found for this signature in database
13 changed files with 185 additions and 17 deletions

1
.unreleased/pr_7832 Normal file
View File

@ -0,0 +1 @@
Implements: #7832 Allow setting chunk_time_interval for continuous aggregates during creation

View File

@ -995,13 +995,6 @@ ts_hyperspace_calculate_point(const Hyperspace *hs, TupleTableSlot *slot)
return p;
}
static inline int64
interval_to_usec(Interval *interval)
{
return (interval->month * DAYS_PER_MONTH * USECS_PER_DAY) + (interval->day * USECS_PER_DAY) +
interval->time;
}
#define INT_TYPE_MAX(type) \
(int64)(((type) == INT2OID) ? PG_INT16_MAX : \
(((type) == INT4OID) ? PG_INT32_MAX : PG_INT64_MAX))

View File

@ -140,7 +140,7 @@ extern int32 ts_dimension_get_hypertable_id(int32 dimension_id);
extern int ts_dimension_set_type(Dimension *dim, Oid newtype);
extern TSDLLEXPORT Oid ts_dimension_get_partition_type(const Dimension *dim);
extern int ts_dimension_set_name(Dimension *dim, const char *newname);
extern int ts_dimension_set_chunk_interval(Dimension *dim, int64 chunk_interval);
extern TSDLLEXPORT int ts_dimension_set_chunk_interval(Dimension *dim, int64 chunk_interval);
extern int ts_dimension_set_compress_interval(Dimension *dim, int64 compress_interval);
extern Datum ts_dimension_transform_value(const Dimension *dim, Oid collation, Datum value,
Oid const_datum_type, Oid *restype);

View File

@ -71,6 +71,10 @@ static const WithClauseDefinition continuous_aggregate_with_clause_def[] = {
.type_id = BOOLOID,
.default_val = (Datum)true,
},
[ContinuousViewOptionChunkTimeInterval] = {
.arg_names = {"chunk_time_interval", NULL},
.type_id = INTERVALOID,
},
[ContinuousViewOptionCompressSegmentBy] = {
.arg_names = {"segmentby", "compress_segmentby", NULL},
.type_id = TEXTOID,

View File

@ -53,6 +53,7 @@ typedef enum ContinuousAggViewOption
ContinuousViewOptionMaterializedOnly,
ContinuousViewOptionCompress,
ContinuousViewOptionFinalized,
ContinuousViewOptionChunkTimeInterval,
ContinuousViewOptionCompressSegmentBy,
ContinuousViewOptionCompressOrderBy,
ContinuousViewOptionCompressChunkTimeInterval,

View File

@ -36,6 +36,13 @@
#define TS_DEBUG_LOG(FMT, ...)
#endif
static inline int64
interval_to_usec(Interval *interval)
{
return (interval->month * DAYS_PER_MONTH * USECS_PER_DAY) + (interval->day * USECS_PER_DAY) +
interval->time;
}
#ifdef TS_DEBUG
static inline const char *

View File

@ -112,7 +112,7 @@ makeMaterializedTableName(char *buf, const char *prefix, int hypertable_id)
static int32 mattablecolumninfo_create_materialization_table(
MatTableColumnInfo *matcolinfo, int32 hypertable_id, RangeVar *mat_rel,
CAggTimebucketInfo *bucket_info, bool create_addl_index, char *tablespacename,
char *table_access_method, ObjectAddress *mataddress);
char *table_access_method, int64 matpartcol_interval, ObjectAddress *mataddress);
static Query *mattablecolumninfo_get_partial_select_query(MatTableColumnInfo *mattblinfo,
Query *userview_query, bool finalized);
@ -419,6 +419,7 @@ mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo,
RangeVar *mat_rel, CAggTimebucketInfo *bucket_info,
bool create_addl_index, char *const tablespacename,
char *const table_access_method,
int64 matpartcol_interval,
ObjectAddress *mataddress)
{
Oid uid, saved_uid;
@ -426,7 +427,6 @@ mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo,
char *matpartcolname = matcolinfo->matpartcolname;
CreateStmt *create;
Datum toast_options;
int64 matpartcol_interval;
static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
int32 mat_htid;
Oid mat_relid;
@ -459,13 +459,6 @@ mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo,
NewRelationCreateToastTable(mat_relid, toast_options);
RESTORE_USER(uid, saved_uid, sec_ctx);
/* Convert the materialization table to a hypertable. */
matpartcol_interval = bucket_info->htpartcol_interval_len;
/* Apply the factor just for non-Hierachical CAggs */
if (bucket_info->parent_mat_hypertable_id == INVALID_HYPERTABLE_ID)
matpartcol_interval *= MATPARTCOL_INTERVAL_FACTOR;
cagg_create_hypertable(hypertable_id, mat_relid, matpartcolname, matpartcol_interval);
/* Retrieve the hypertable id from the cache. */
@ -678,6 +671,21 @@ cagg_create(const CreateTableAsStmt *create_stmt, ViewStmt *stmt, Query *panquer
DatumGetBool(with_clause_options[ContinuousViewOptionMaterializedOnly].parsed);
bool finalized = DatumGetBool(with_clause_options[ContinuousViewOptionFinalized].parsed);
int64 matpartcol_interval = 0;
if (!with_clause_options[ContinuousViewOptionChunkTimeInterval].is_default)
{
matpartcol_interval = interval_to_usec(
DatumGetIntervalP(with_clause_options[ContinuousViewOptionChunkTimeInterval].parsed));
}
else
{
matpartcol_interval = bucket_info->htpartcol_interval_len;
/* Apply the factor just for non-Hierachical CAggs */
if (bucket_info->parent_mat_hypertable_id == INVALID_HYPERTABLE_ID)
matpartcol_interval *= MATPARTCOL_INTERVAL_FACTOR;
}
finalqinfo.finalized = finalized;
/*
@ -714,6 +722,7 @@ cagg_create(const CreateTableAsStmt *create_stmt, ViewStmt *stmt, Query *panquer
is_create_mattbl_index,
create_stmt->into->tableSpaceName,
create_stmt->into->accessMethod,
matpartcol_interval,
&mataddress);
/*
* Step 2: Create view with select finalize from materialization table.

View File

@ -185,6 +185,19 @@ continuous_agg_update_options(ContinuousAgg *agg, WithClauseResult *with_clause_
cagg_update_materialized_only(agg, materialized_only);
ts_cache_release(hcache);
}
if (!with_clause_options[ContinuousViewOptionChunkTimeInterval].is_default)
{
Cache *hcache = ts_hypertable_cache_pin();
Hypertable *mat_ht =
ts_hypertable_cache_get_entry_by_id(hcache, agg->data.mat_hypertable_id);
int64 interval = interval_to_usec(
DatumGetIntervalP(with_clause_options[ContinuousViewOptionChunkTimeInterval].parsed));
Dimension *dim = ts_hyperspace_get_mutable_dimension(mat_ht->space, DIMENSION_TYPE_OPEN, 0);
ts_dimension_set_chunk_interval(dim, interval);
ts_cache_release(hcache);
}
List *compression_options = ts_continuous_agg_get_compression_defelems(with_clause_options);
if (list_length(compression_options) > 0)

View File

@ -2129,3 +2129,34 @@ SELECT time_bucket(INTERVAL '1 day', time) FROM conditions GROUP BY 1 WITH NO DA
ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false);
ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false);
DROP MATERIALIZED VIEW cagg_alias;
-- test SET chunk_time_interval
CREATE MATERIALIZED VIEW cagg_set
WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS
SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA;
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 1 day
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 23 days
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 180 days
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 360 days
(1 row)

View File

@ -2129,3 +2129,34 @@ SELECT time_bucket(INTERVAL '1 day', time) FROM conditions GROUP BY 1 WITH NO DA
ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false);
ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false);
DROP MATERIALIZED VIEW cagg_alias;
-- test SET chunk_time_interval
CREATE MATERIALIZED VIEW cagg_set
WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS
SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA;
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 1 day
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 23 days
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 180 days
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 360 days
(1 row)

View File

@ -2129,3 +2129,34 @@ SELECT time_bucket(INTERVAL '1 day', time) FROM conditions GROUP BY 1 WITH NO DA
ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false);
ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false);
DROP MATERIALIZED VIEW cagg_alias;
-- test SET chunk_time_interval
CREATE MATERIALIZED VIEW cagg_set
WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS
SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA;
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 1 day
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 23 days
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 180 days
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 360 days
(1 row)

View File

@ -2129,3 +2129,34 @@ SELECT time_bucket(INTERVAL '1 day', time) FROM conditions GROUP BY 1 WITH NO DA
ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false);
ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false);
DROP MATERIALIZED VIEW cagg_alias;
-- test SET chunk_time_interval
CREATE MATERIALIZED VIEW cagg_set
WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS
SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA;
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 1 day
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 23 days
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 180 days
(1 row)
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
column_name | time_interval
----------------------+---------------
cagg_interval_setter | @ 360 days
(1 row)

View File

@ -1357,3 +1357,19 @@ ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false);
ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false);
DROP MATERIALIZED VIEW cagg_alias;
-- test SET chunk_time_interval
CREATE MATERIALIZED VIEW cagg_set
WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS
SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA;
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';
ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year');
SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';