mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-16 10:33:27 +08:00
This patch allows using custom origin's in CAGGs, for instance: time_bucket_ng('7 days', day, '2000-01-03' :: date) AS bucket For weekly buckets this allows the user to choose what should be considered the beginning of the week - Sunday or Monday. Also by shifting the origin one second forward or backward user can tweak the inclusiveness of the buckets. This works for date's, timestamp's and timestamptz's. The bucket size is considered variable-sized in all these cases. CAGGs on top of distributed hypertables, compressed hypertables and compressed distributed hypertables are supported as well. Additionally, this patch does several small refactorings. Firstly, it makes sure that experimental features of CAGGs will be tested in both Debug and Release builds. This was previously overlooked. Secondly, it renames the tests so that a person who is working on experimental features in CAGGs will be able to easily execute all the related tests: `TESTS='exp_cagg_*' make installcheck` Last but not least the patch refactors is_valid_bucketing_function() and renames it to function_allowed_in_cagg_definition(). The reason to do it in this patch is that otherwise, the logic of the function gets rather confusing which complicates code review. fix
603 lines
22 KiB
SQL
603 lines
22 KiB
SQL
-- 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.
|
|
|
|
-- Make sure that timezone can't be used for types other that timestamptz
|
|
|
|
CREATE TABLE conditions(
|
|
day timestamp NOT NULL, -- not timestamptz!
|
|
city text NOT NULL,
|
|
temperature INT NOT NULL);
|
|
|
|
SELECT create_hypertable(
|
|
'conditions', 'day',
|
|
chunk_time_interval => INTERVAL '1 day'
|
|
);
|
|
|
|
\set ON_ERROR_STOP 0
|
|
CREATE MATERIALIZED VIEW conditions
|
|
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('1 month', day, 'Europe/Moscow') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions
|
|
GROUP BY city, bucket
|
|
WITH NO DATA;
|
|
\set ON_ERROR_STOP 1
|
|
|
|
DROP TABLE conditions CASCADE;
|
|
|
|
CREATE TABLE conditions_tz(
|
|
day timestamptz NOT NULL,
|
|
city text NOT NULL,
|
|
temperature INT NOT NULL);
|
|
|
|
SELECT create_hypertable(
|
|
'conditions_tz', 'day',
|
|
chunk_time_interval => INTERVAL '1 day'
|
|
);
|
|
|
|
INSERT INTO conditions_tz (day, city, temperature) VALUES
|
|
('2021-06-14 00:00:00 MSK', 'Moscow', 26),
|
|
('2021-06-15 00:00:00 MSK', 'Moscow', 22),
|
|
('2021-06-16 00:00:00 MSK', 'Moscow', 24),
|
|
('2021-06-17 00:00:00 MSK', 'Moscow', 24),
|
|
('2021-06-18 00:00:00 MSK', 'Moscow', 27),
|
|
('2021-06-19 00:00:00 MSK', 'Moscow', 28),
|
|
('2021-06-20 00:00:00 MSK', 'Moscow', 30),
|
|
('2021-06-21 00:00:00 MSK', 'Moscow', 31),
|
|
('2021-06-22 00:00:00 MSK', 'Moscow', 34),
|
|
('2021-06-23 00:00:00 MSK', 'Moscow', 34),
|
|
('2021-06-24 00:00:00 MSK', 'Moscow', 34),
|
|
('2021-06-25 00:00:00 MSK', 'Moscow', 32),
|
|
('2021-06-26 00:00:00 MSK', 'Moscow', 32),
|
|
('2021-06-27 00:00:00 MSK', 'Moscow', 31);
|
|
|
|
\set ON_ERROR_STOP 0
|
|
|
|
-- Check that the name of the timezone is validated
|
|
|
|
CREATE MATERIALIZED VIEW conditions_summary_tz
|
|
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('1 month', day, 'Europe/Ololondon') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_tz
|
|
GROUP BY city, bucket
|
|
WITH NO DATA;
|
|
|
|
-- Check that buckets like '1 month 15 days' (fixed-sized + variable-sized) are not allowed
|
|
|
|
CREATE MATERIALIZED VIEW conditions_summary_tz
|
|
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('1 month 15 days', day, 'MSK') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_tz
|
|
GROUP BY city, bucket
|
|
WITH NO DATA;
|
|
|
|
-- Check that only immutable expressions can be used as a timezone
|
|
|
|
CREATE MATERIALIZED VIEW conditions_summary_tz
|
|
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('1 day', day, city) AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_tz
|
|
GROUP BY city, bucket
|
|
WITH NO DATA;
|
|
|
|
\set ON_ERROR_STOP 1
|
|
|
|
-- Make sure it's possible to create an empty cagg (WITH NO DATA) and
|
|
-- that all the information about the bucketing function will be saved
|
|
-- to the TS catalog.
|
|
|
|
CREATE MATERIALIZED VIEW conditions_summary_tz
|
|
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('1 month', day, 'MSK') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_tz
|
|
GROUP BY city, bucket
|
|
WITH NO DATA;
|
|
|
|
SELECT mat_hypertable_id AS cagg_id_tz, raw_hypertable_id AS ht_id
|
|
FROM _timescaledb_catalog.continuous_agg
|
|
WHERE user_view_name = 'conditions_summary_tz'
|
|
\gset
|
|
|
|
SELECT bucket_width
|
|
FROM _timescaledb_catalog.continuous_agg
|
|
WHERE mat_hypertable_id = :cagg_id_tz;
|
|
|
|
-- Make sure the timezone is saved in the catalog table
|
|
SELECT experimental, name, bucket_width, origin, timezone
|
|
FROM _timescaledb_catalog.continuous_aggs_bucket_function
|
|
WHERE mat_hypertable_id = :cagg_id_tz;
|
|
|
|
-- Make sure that buckets with specified timezone are always treated as
|
|
-- variable-sized, even if the interval is fixed (i.e. days and/or hours)
|
|
|
|
CREATE MATERIALIZED VIEW conditions_summary_1w
|
|
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('7 days', day, 'MSK') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_tz
|
|
GROUP BY city, bucket
|
|
WITH NO DATA;
|
|
|
|
SELECT mat_hypertable_id AS cagg_id_1w
|
|
FROM _timescaledb_catalog.continuous_agg
|
|
WHERE user_view_name = 'conditions_summary_1w'
|
|
\gset
|
|
|
|
SELECT bucket_width
|
|
FROM _timescaledb_catalog.continuous_agg
|
|
WHERE mat_hypertable_id = :cagg_id_1w;
|
|
|
|
-- Make sure the timezone is saved in the catalog table
|
|
SELECT experimental, name, bucket_width, origin, timezone
|
|
FROM _timescaledb_catalog.continuous_aggs_bucket_function
|
|
WHERE mat_hypertable_id = :cagg_id_1w;
|
|
|
|
-- Check the invalidation threshold
|
|
SELECT to_char(_timescaledb_internal.to_timestamp(watermark) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS')
|
|
FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
-- Make sure the invalidation log is empty
|
|
SELECT
|
|
to_char(_timescaledb_internal.to_timestamp(lowest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS lowest,
|
|
to_char(_timescaledb_internal.to_timestamp(greatest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS greatest
|
|
FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
-- Make sure truncating of the refresh window works
|
|
\set ON_ERROR_STOP 0
|
|
CALL refresh_continuous_aggregate('conditions_summary_tz', '2021-07-02 MSK', '2021-07-12 MSK');
|
|
CALL refresh_continuous_aggregate('conditions_summary_1w', '2021-07-02 MSK', '2021-07-05 MSK');
|
|
\set ON_ERROR_STOP 1
|
|
|
|
-- Make sure refreshing works
|
|
CALL refresh_continuous_aggregate('conditions_summary_tz', '2021-06-01 MSK', '2021-07-01 MSK');
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_tz
|
|
ORDER by month, city;
|
|
|
|
-- Check the invalidation threshold
|
|
|
|
SELECT to_char(_timescaledb_internal.to_timestamp(watermark) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS')
|
|
FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
-- The default origin is Saturday. Here we do refresh only for two full weeks
|
|
-- in June in order to keep the invalidation threshold as it is.
|
|
CALL refresh_continuous_aggregate('conditions_summary_1w', '2021-06-12 MSK', '2021-06-26 MSK');
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as week, min, max
|
|
FROM conditions_summary_1w
|
|
ORDER by week, city;
|
|
|
|
-- Check the invalidation threshold
|
|
|
|
SELECT to_char(_timescaledb_internal.to_timestamp(watermark) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS')
|
|
FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
-- Make sure creating CAGGs without NO DATA works the same way
|
|
|
|
CREATE MATERIALIZED VIEW conditions_summary_tz2
|
|
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('1 month', day, 'MSK') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_tz
|
|
GROUP BY city, bucket;
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_tz2
|
|
ORDER by month, city;
|
|
|
|
-- Add some dummy data for two more months (no invalidations test case)
|
|
INSERT INTO conditions_tz (day, city, temperature)
|
|
SELECT ts, city, row_number() OVER ()
|
|
FROM generate_series('2021-07-01 MSK' :: timestamptz, '2021-08-31 MSK', '3 day') as ts,
|
|
unnest(array['Moscow', 'Berlin']) as city;
|
|
|
|
-- Double check the generated data
|
|
SELECT to_char(day at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS'), city, temperature
|
|
FROM conditions_tz
|
|
WHERE day >= '2021-07-01 MSK'
|
|
ORDER BY city DESC, day;
|
|
|
|
-- Make sure the invalidation threshold was unaffected
|
|
SELECT to_char(_timescaledb_internal.to_timestamp(watermark) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS')
|
|
FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
-- Make sure the invalidation log is still empty
|
|
SELECT
|
|
to_char(_timescaledb_internal.to_timestamp(lowest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS lowest,
|
|
to_char(_timescaledb_internal.to_timestamp(greatest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS greatest
|
|
FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
-- Call refresh for two full buckets: 2021-07-01 and 2021-08-01
|
|
CALL refresh_continuous_aggregate('conditions_summary_tz', '2021-06-15 MSK', '2021-09-15 MSK');
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_tz
|
|
ORDER by month, city;
|
|
|
|
-- Make sure the invalidation threshold has changed
|
|
SELECT to_char(_timescaledb_internal.to_timestamp(watermark) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS')
|
|
FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
-- Make sure the invalidation log is still empty
|
|
SELECT
|
|
to_char(_timescaledb_internal.to_timestamp(lowest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS lowest,
|
|
to_char(_timescaledb_internal.to_timestamp(greatest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS greatest
|
|
FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
-- Add more data below the invalidation threshold, make sure that the
|
|
-- invalidation log is not empty, then do a refresh.
|
|
INSERT INTO conditions_tz (day, city, temperature)
|
|
SELECT ts :: timestamptz, city, (CASE WHEN city = 'Moscow' THEN -100 ELSE 100 END)
|
|
FROM generate_series('2021-08-16 MSK' :: timestamptz, '2021-08-30 MSK', '1 day') as ts,
|
|
unnest(array['Moscow', 'Berlin']) as city;
|
|
|
|
SELECT
|
|
to_char(_timescaledb_internal.to_timestamp(lowest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS lowest,
|
|
to_char(_timescaledb_internal.to_timestamp(greatest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS greatest
|
|
FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
CALL refresh_continuous_aggregate('conditions_summary_tz', '2021-08-01 MSK', '2021-09-01 MSK');
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_tz
|
|
ORDER by month, city;
|
|
|
|
SELECT
|
|
to_char(_timescaledb_internal.to_timestamp(lowest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS lowest,
|
|
to_char(_timescaledb_internal.to_timestamp(greatest_modified_value) at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') AS greatest
|
|
FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log
|
|
WHERE hypertable_id = :ht_id;
|
|
|
|
-- Clean up
|
|
DROP MATERIALIZED VIEW conditions_summary_tz;
|
|
DROP MATERIALIZED VIEW conditions_summary_1w;
|
|
|
|
-- Create a real-time aggregate
|
|
CREATE MATERIALIZED VIEW conditions_summary_tz
|
|
WITH (timescaledb.continuous) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('1 month', day, 'MSK') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_tz
|
|
GROUP BY city, bucket;
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_tz
|
|
ORDER by month, city;
|
|
|
|
-- Add some data to the hypertable and make sure they are visible in the cagg
|
|
INSERT INTO conditions_tz (day, city, temperature) VALUES
|
|
('2021-10-01 00:00:00 MSK', 'Moscow', 1),
|
|
('2021-10-02 00:00:00 MSK', 'Moscow', 2),
|
|
('2021-10-03 00:00:00 MSK', 'Moscow', 3),
|
|
('2021-10-04 00:00:00 MSK', 'Moscow', 4),
|
|
('2021-10-01 00:00:00 MSK', 'Berlin', 5),
|
|
('2021-10-02 00:00:00 MSK', 'Berlin', 6),
|
|
('2021-10-03 00:00:00 MSK', 'Berlin', 7),
|
|
('2021-10-04 00:00:00 MSK', 'Berlin', 8);
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_tz
|
|
ORDER by month, city;
|
|
|
|
-- Refresh the cagg and make sure that the result of SELECT query didn't change
|
|
CALL refresh_continuous_aggregate('conditions_summary_tz', '2021-10-01 00:00:00 MSK', '2021-11-01 00:00:00 MSK');
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_tz
|
|
ORDER by month, city;
|
|
|
|
-- Add some more data, enable compression, compress the chunks and repeat the test
|
|
|
|
INSERT INTO conditions_tz (day, city, temperature) VALUES
|
|
('2021-11-01 00:00:00 MSK', 'Moscow', 11),
|
|
('2021-11-02 00:00:00 MSK', 'Moscow', 12),
|
|
('2021-11-03 00:00:00 MSK', 'Moscow', 13),
|
|
('2021-11-04 00:00:00 MSK', 'Moscow', 14),
|
|
('2021-11-01 00:00:00 MSK', 'Berlin', 15),
|
|
('2021-11-02 00:00:00 MSK', 'Berlin', 16),
|
|
('2021-11-03 00:00:00 MSK', 'Berlin', 17),
|
|
('2021-11-04 00:00:00 MSK', 'Berlin', 18);
|
|
|
|
ALTER TABLE conditions_tz SET (
|
|
timescaledb.compress,
|
|
timescaledb.compress_segmentby = 'city'
|
|
);
|
|
|
|
SELECT compress_chunk(ch) FROM show_chunks('conditions_tz') AS ch;
|
|
|
|
-- Data for 2021-11 is seen because the cagg is real-time
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_tz
|
|
ORDER by month, city;
|
|
|
|
CALL refresh_continuous_aggregate('conditions_summary_tz', '2021-11-01 00:00:00 MSK', '2021-12-01 00:00:00 MSK');
|
|
|
|
-- Data for 2021-11 is seen because the cagg was refreshed
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_tz
|
|
ORDER by month, city;
|
|
|
|
-- Test for some more cases: single CAGG per HT, creating CAGG on top of an
|
|
-- empty HT, buckets other than 1 month.
|
|
|
|
CREATE TABLE conditions2(
|
|
day timestamptz NOT NULL,
|
|
city text NOT NULL,
|
|
temperature INT NOT NULL);
|
|
|
|
SELECT create_hypertable(
|
|
'conditions2', 'day',
|
|
chunk_time_interval => INTERVAL '1 day'
|
|
);
|
|
|
|
-- Create a real-time aggregate on top of empty HT
|
|
CREATE MATERIALIZED VIEW conditions2_summary
|
|
WITH (timescaledb.continuous) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('7 days', day, 'MSK') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions2
|
|
GROUP BY city, bucket;
|
|
|
|
INSERT INTO conditions2 (day, city, temperature) VALUES
|
|
('2021-06-14 00:00:00 MSK', 'Moscow', 26),
|
|
('2021-06-15 00:00:00 MSK', 'Moscow', 22),
|
|
('2021-06-16 00:00:00 MSK', 'Moscow', 24),
|
|
('2021-06-17 00:00:00 MSK', 'Moscow', 24),
|
|
('2021-06-18 00:00:00 MSK', 'Moscow', 27),
|
|
('2021-06-19 00:00:00 MSK', 'Moscow', 28),
|
|
('2021-06-20 00:00:00 MSK', 'Moscow', 30),
|
|
('2021-06-21 00:00:00 MSK', 'Moscow', 31),
|
|
('2021-06-22 00:00:00 MSK', 'Moscow', 34),
|
|
('2021-06-23 00:00:00 MSK', 'Moscow', 34),
|
|
('2021-06-24 00:00:00 MSK', 'Moscow', 34),
|
|
('2021-06-25 00:00:00 MSK', 'Moscow', 32),
|
|
('2021-06-26 00:00:00 MSK', 'Moscow', 32),
|
|
('2021-06-27 00:00:00 MSK', 'Moscow', 31);
|
|
|
|
-- All data should be seen for a real-time aggregate
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions2_summary
|
|
ORDER by month, city;
|
|
|
|
-- Refresh should work
|
|
CALL refresh_continuous_aggregate('conditions2_summary', '2021-06-12 MSK', '2021-07-03 MSK');
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions2_summary
|
|
ORDER by month, city;
|
|
|
|
-- New data should be seen
|
|
INSERT INTO conditions2 (day, city, temperature) VALUES
|
|
('2021-09-30 00:00:00 MSK', 'Moscow', 0),
|
|
('2021-10-01 00:00:00 MSK', 'Moscow', 1),
|
|
('2021-10-02 00:00:00 MSK', 'Moscow', 2),
|
|
('2021-10-03 00:00:00 MSK', 'Moscow', 3),
|
|
('2021-10-04 00:00:00 MSK', 'Moscow', 4),
|
|
('2021-09-30 00:00:00 MSK', 'Berlin', 5),
|
|
('2021-10-01 00:00:00 MSK', 'Berlin', 6),
|
|
('2021-10-02 00:00:00 MSK', 'Berlin', 7),
|
|
('2021-10-03 00:00:00 MSK', 'Berlin', 8),
|
|
('2021-10-04 00:00:00 MSK', 'Berlin', 9);
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions2_summary
|
|
ORDER by month, city;
|
|
|
|
-- Test caggs with monthly buckets on top of distributed hypertable
|
|
\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER
|
|
\set DATA_NODE_1 :TEST_DBNAME _1
|
|
\set DATA_NODE_2 :TEST_DBNAME _2
|
|
\set DATA_NODE_3 :TEST_DBNAME _3
|
|
|
|
SELECT (add_data_node (name, host => 'localhost', DATABASE => name)).*
|
|
FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v (name);
|
|
|
|
GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC;
|
|
|
|
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
|
|
|
CREATE TABLE conditions_dist(
|
|
day timestamptz NOT NULL,
|
|
temperature INT NOT NULL);
|
|
|
|
SELECT table_name FROM create_distributed_hypertable('conditions_dist', 'day', chunk_time_interval => INTERVAL '1 day');
|
|
|
|
INSERT INTO conditions_dist(day, temperature)
|
|
SELECT ts, date_part('month', ts)*100 + date_part('day', ts)
|
|
FROM generate_series('2010-01-01 00:00:00 MSK' :: timestamptz, '2010-03-01 00:00:00 MSK' :: timestamptz - interval '1 day', '1 day') as ts;
|
|
|
|
CREATE MATERIALIZED VIEW conditions_dist_1m
|
|
WITH (timescaledb.continuous) AS
|
|
SELECT
|
|
timescaledb_experimental.time_bucket_ng('1 month', day, 'MSK') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_dist
|
|
GROUP BY bucket;
|
|
|
|
SELECT mat_hypertable_id AS cagg_id
|
|
FROM _timescaledb_catalog.continuous_agg
|
|
WHERE user_view_name = 'conditions_dist_1m'
|
|
\gset
|
|
|
|
SELECT raw_hypertable_id AS ht_id
|
|
FROM _timescaledb_catalog.continuous_agg
|
|
WHERE user_view_name = 'conditions_dist_1m'
|
|
\gset
|
|
|
|
SELECT bucket_width
|
|
FROM _timescaledb_catalog.continuous_agg
|
|
WHERE mat_hypertable_id = :cagg_id;
|
|
|
|
SELECT experimental, name, bucket_width, origin, timezone
|
|
FROM _timescaledb_catalog.continuous_aggs_bucket_function
|
|
WHERE mat_hypertable_id = :cagg_id;
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m
|
|
ORDER BY month;
|
|
|
|
-- Same test but with non-realtime, NO DATA aggregate and manual refresh
|
|
|
|
CREATE MATERIALIZED VIEW conditions_dist_1m_manual
|
|
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
|
|
SELECT
|
|
timescaledb_experimental.time_bucket_ng('1 month', day, 'MSK') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_dist
|
|
GROUP BY bucket
|
|
WITH NO DATA;
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m_manual
|
|
ORDER BY month;
|
|
|
|
CALL refresh_continuous_aggregate('conditions_dist_1m_manual', '2010-01-01 00:00:00 MSK', '2010-03-01 00:00:00 MSK');
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m_manual
|
|
ORDER BY month;
|
|
|
|
-- Check invalidation for caggs on top of distributed hypertable
|
|
|
|
INSERT INTO conditions_dist(day, temperature) VALUES
|
|
('2010-01-15 00:00:00 MSK', 999),
|
|
('2010-02-15 00:00:00 MSK', -999),
|
|
('2010-03-01 00:00:00 MSK', 15);
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m
|
|
ORDER BY month;
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m_manual
|
|
ORDER BY month;
|
|
|
|
CALL refresh_continuous_aggregate('conditions_dist_1m', '2010-01-01 00:00:00 MSK', '2010-04-01 00:00:00 MSK');
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m
|
|
ORDER BY month;
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m_manual
|
|
ORDER BY month;
|
|
|
|
CALL refresh_continuous_aggregate('conditions_dist_1m_manual', '2010-01-01 00:00:00 MSK', '2010-04-01 00:00:00 MSK');
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m
|
|
ORDER BY month;
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m_manual
|
|
ORDER BY month;
|
|
|
|
-- Check compatibility with compressed distributed hypertables
|
|
|
|
ALTER MATERIALIZED VIEW conditions_dist_1m_manual SET ( timescaledb.compress );
|
|
|
|
SELECT compress_chunk(ch)
|
|
FROM show_chunks('conditions_dist_1m_manual') ch limit 1;
|
|
|
|
SELECT to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_dist_1m_manual
|
|
ORDER BY month;
|
|
|
|
-- Clean up
|
|
DROP TABLE conditions_dist CASCADE;
|
|
|
|
\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER;
|
|
DROP DATABASE :DATA_NODE_1;
|
|
DROP DATABASE :DATA_NODE_2;
|
|
DROP DATABASE :DATA_NODE_3;
|
|
|
|
-- Make sure add_continuous_aggregate_policy() works
|
|
|
|
CREATE TABLE conditions_policy(
|
|
day TIMESTAMPTZ NOT NULL,
|
|
city text NOT NULL,
|
|
temperature INT NOT NULL);
|
|
|
|
SELECT create_hypertable(
|
|
'conditions_policy', 'day',
|
|
chunk_time_interval => INTERVAL '1 day'
|
|
);
|
|
|
|
INSERT INTO conditions_policy (day, city, temperature) VALUES
|
|
('2021-06-14 00:00:00 MSK', 'Moscow', 26),
|
|
('2021-06-14 10:00:00 MSK', 'Moscow', 22),
|
|
('2021-06-14 20:00:00 MSK', 'Moscow', 24),
|
|
('2021-06-15 00:00:00 MSK', 'Moscow', 24),
|
|
('2021-06-15 10:00:00 MSK', 'Moscow', 27),
|
|
('2021-06-15 20:00:00 MSK', 'Moscow', 28),
|
|
('2021-06-16 00:00:00 MSK', 'Moscow', 30),
|
|
('2021-06-16 10:00:00 MSK', 'Moscow', 31),
|
|
('2021-06-16 20:00:00 MSK', 'Moscow', 34),
|
|
('2021-06-17 00:00:00 MSK', 'Moscow', 34),
|
|
('2021-06-17 10:00:00 MSK', 'Moscow', 34),
|
|
('2021-06-17 20:00:00 MSK', 'Moscow', 32),
|
|
('2021-06-18 00:00:00 MSK', 'Moscow', 32),
|
|
('2021-06-18 10:00:00 MSK', 'Moscow', 31),
|
|
('2021-06-18 20:00:00 MSK', 'Moscow', 26);
|
|
|
|
CREATE MATERIALIZED VIEW conditions_summary_policy
|
|
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
|
|
SELECT city,
|
|
timescaledb_experimental.time_bucket_ng('1 day', day, 'Europe/Moscow') AS bucket,
|
|
MIN(temperature),
|
|
MAX(temperature)
|
|
FROM conditions_policy
|
|
GROUP BY city, bucket;
|
|
|
|
SELECT city, to_char(bucket at time zone 'MSK', 'YYYY-MM-DD HH24:MI:SS') as month, min, max
|
|
FROM conditions_summary_policy
|
|
ORDER by month, city;
|
|
|
|
\set ON_ERROR_STOP 0
|
|
-- Check for "policy refresh window too small" error
|
|
SELECT add_continuous_aggregate_policy('conditions_summary_policy',
|
|
start_offset => INTERVAL '2 days 23 hours',
|
|
end_offset => INTERVAL '1 day',
|
|
schedule_interval => INTERVAL '1 hour');
|
|
\set ON_ERROR_STOP 1
|
|
|
|
SELECT add_continuous_aggregate_policy('conditions_summary_policy',
|
|
start_offset => INTERVAL '3 days',
|
|
end_offset => INTERVAL '1 day',
|
|
schedule_interval => INTERVAL '1 hour');
|