timescaledb/test/sql/chunk_adaptive.sql
Erik Nordström 9c9cdca6d3 Add support for adaptive chunk sizing
Users can now (optionally) set a target chunk size and TimescaleDB
will try to adapt the interval length of the first open ("time")
dimension in order to reach that target chunk size. If a hypertable
has more than one open dimension, only the first one will have a
dynamically adapting interval.

Users can optionally specify their own function that calculates the
new dimension interval. They can also set a target size of 0 in order
to estimate a suitable target size for a chunk based on available
memory.
2018-08-08 17:01:31 +02:00

152 lines
6.0 KiB
PL/PgSQL

-- Valid chunk sizing function for testing
CREATE OR REPLACE FUNCTION calculate_chunk_interval(
dimension_id INTEGER,
dimension_coord BIGINT,
chunk_target_size BIGINT
)
RETURNS BIGINT LANGUAGE PLPGSQL AS
$BODY$
DECLARE
BEGIN
RETURN -1;
END
$BODY$;
-- Chunk sizing function with bad signature
CREATE OR REPLACE FUNCTION bad_calculate_chunk_interval(
dimension_id INTEGER
)
RETURNS BIGINT LANGUAGE PLPGSQL AS
$BODY$
DECLARE
BEGIN
RETURN -1;
END
$BODY$;
-- Set a fixed effective memory cache size to make tests determinstic
-- (independent of available machine memory)
SELECT * FROM test.set_effective_memory_cache_size('2GB');
CREATE TABLE test_adaptive(time timestamptz, temp float, location int);
\set ON_ERROR_STOP 0
-- Bad signature of sizing func should fail
SELECT create_hypertable('test_adaptive', 'time',
chunk_target_size => '1MB',
chunk_sizing_func => 'bad_calculate_chunk_interval');
\set ON_ERROR_STOP 1
-- Setting sizing func with correct signature should work
SELECT create_hypertable('test_adaptive', 'time',
chunk_target_size => '1MB',
chunk_sizing_func => 'calculate_chunk_interval');
DROP TABLE test_adaptive;
CREATE TABLE test_adaptive(time timestamptz, temp float, location int);
-- Size but no explicit func should use default func
SELECT create_hypertable('test_adaptive', 'time',
chunk_target_size => '1MB',
create_default_indexes => true);
SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size
FROM _timescaledb_catalog.hypertable;
-- Change the target size
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', '2MB');
SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size
FROM _timescaledb_catalog.hypertable;
\set ON_ERROR_STOP 0
-- Setting NULL func should fail
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', '1MB', NULL);
\set ON_ERROR_STOP 1
-- Setting NULL size disables adaptive chunking
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', NULL);
SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size
FROM _timescaledb_catalog.hypertable;
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', '1MB');
-- Setting size to 'off' should also disable
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', 'off');
SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size
FROM _timescaledb_catalog.hypertable;
-- Setting 0 size should do an estimate.
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', '0MB');
SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size
FROM _timescaledb_catalog.hypertable;
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', '1MB');
-- Setting size to 'estimate' should also estimate size
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', 'estimate');
SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size
FROM _timescaledb_catalog.hypertable;
-- Use a lower memory setting to test that the calculated chunk_target_size is reduced
SELECT * FROM test.set_effective_memory_cache_size('512MB');
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', 'estimate');
SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size
FROM _timescaledb_catalog.hypertable;
-- Reset memory settings
SELECT * FROM test.set_effective_memory_cache_size('2GB');
-- Set a reasonable test value
SELECT * FROM set_adaptive_chunk_sizing('test_adaptive', '1MB');
-- Show the interval length before and after adaptation
SELECT id, hypertable_id, interval_length FROM _timescaledb_catalog.dimension;
-- Generate data to create chunks. We use the hash of the time value
-- to get determinstic location IDs so that we always spread these
-- values the same way across space partitions
INSERT INTO test_adaptive
SELECT time, random() * 35, _timescaledb_internal.get_partition_hash(time) FROM
generate_series('2017-03-07T18:18:03+00'::timestamptz - interval '175 days',
'2017-03-07T18:18:03+00'::timestamptz,
'2 minutes') as time;
SELECT * FROM chunk_relation_size('test_adaptive');
-- Do same thing without an index on the time column. This affects
-- both the calculation of fill-factor of the chunk and its size
CREATE TABLE test_adaptive_no_index(time timestamptz, temp float, location int);
-- Size but no explicit func should use default func
SELECT create_hypertable('test_adaptive_no_index', 'time',
chunk_target_size => '1MB',
create_default_indexes => false);
SELECT id, hypertable_id, interval_length FROM _timescaledb_catalog.dimension;
INSERT INTO test_adaptive_no_index
SELECT time, random() * 35, _timescaledb_internal.get_partition_hash(time) FROM
generate_series('2017-03-07T18:18:03+00'::timestamptz - interval '175 days',
'2017-03-07T18:18:03+00'::timestamptz,
'2 minutes') as time;
SELECT * FROM chunk_relation_size('test_adaptive_no_index');
-- Test with space partitioning. This might affect the estimation
-- since there are more chunks in the same time interval and space
-- chunks might be unevenly filled.
CREATE TABLE test_adaptive_space(time timestamptz, temp float, location int);
SELECT create_hypertable('test_adaptive_space', 'time', 'location', 2,
chunk_target_size => '1MB',
create_default_indexes => true);
SELECT id, hypertable_id, interval_length FROM _timescaledb_catalog.dimension;
INSERT INTO test_adaptive_space
SELECT time, random() * 35, _timescaledb_internal.get_partition_hash(time) FROM
generate_series('2017-03-07T18:18:03+00'::timestamptz - interval '175 days',
'2017-03-07T18:18:03+00'::timestamptz,
'2 minutes') as time;
SELECT * FROM chunk_relation_size('test_adaptive_space');
SELECT id, hypertable_id, interval_length FROM _timescaledb_catalog.dimension;