Skip to content

Commit

Permalink
Show warning for inefficient compress_chunk_interval configuration
Browse files Browse the repository at this point in the history
When compress_chunk_time_interval is configured but compress_orderby
does not have the primary dimension as first column, chunk merging will
be less efficient as chunks have to be decompressed to be merged.
This patch adds a warning when we encounter this configuration.
  • Loading branch information
svenklemm committed Mar 4, 2025
1 parent 4ebfedf commit 9115e12
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 0 deletions.
1 change: 1 addition & 0 deletions .unreleased/pr_7786
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implements: #7786 Show warning for inefficient compress_chunk_time_interval configuration
19 changes: 19 additions & 0 deletions tsl/src/compression/create.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,25 @@ tsl_process_compress_table(AlterTableCmd *cmd, Hypertable *ht,
ts_hypertable_set_compressed(ht, compress_htid);
}

/*
* Check for suboptimal compressed chunk merging configuration
*
* When compress_chunk_time_interval is configured to merge chunks during compression the
* primary dimension should be the first compress_orderby column otherwise chunk merging will
* require decompression.
*/
Dimension *dim = ts_hyperspace_get_mutable_dimension(ht->space, DIMENSION_TYPE_OPEN, 0);
if (dim && dim->fd.compress_interval_length &&
ts_array_position(settings->fd.orderby, NameStr(dim->fd.column_name)) != 1)
{
ereport(WARNING,
(errcode(ERRCODE_WARNING),
errmsg("compress_chunk_time_interval configured and primary dimension not "
"first column in compress_orderby"),
errhint("consider setting \"%s\" as first compress_orderby column",
NameStr(dim->fd.column_name))));
}

/* do not release any locks, will get released by xact end */
return true;
}
Expand Down
13 changes: 13 additions & 0 deletions tsl/test/expected/compression_merge.out
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ SELECT t, i, gen_rand_minstd()
FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-03 0:59', '1 minute') t
CROSS JOIN generate_series(1, 5, 1) i;
-- Compression is set to merge those 24 chunks into 3 chunks, two 10 hour chunks and a single 4 hour chunk.
\set VERBOSITY default
ALTER TABLE test2 set (timescaledb.compress, timescaledb.compress_segmentby='i', timescaledb.compress_orderby='loc,"Time"', timescaledb.compress_chunk_time_interval='10 hours');
WARNING: compress_chunk_time_interval configured and primary dimension not first column in compress_orderby
HINT: consider setting "Time" as first compress_orderby column
\set VERBOSITY terse
-- Verify we are fully recompressing unordered chunks
BEGIN;
SELECT count(compress_chunk(chunk, true)) FROM show_chunks('test2') chunk;
Expand Down Expand Up @@ -202,9 +206,13 @@ INSERT INTO test3 SELECT t, 1, gen_rand_minstd(), gen_rand_minstd() FROM generat
INSERT INTO test3 SELECT t, 2, gen_rand_minstd(), gen_rand_minstd() FROM generate_series('2018-03-02 13:00'::TIMESTAMPTZ, '2018-03-03 0:59', '1 minute') t;
INSERT INTO test3 SELECT t, 3, gen_rand_minstd(), gen_rand_minstd() FROM generate_series('2018-03-02 2:00'::TIMESTAMPTZ, '2018-03-02 2:01', '1 minute') t;
-- Compression is set to merge those 25 chunks into 12 2 hour chunks and a single 1 hour chunks on a different space dimensions.
\set VERBOSITY default
ALTER TABLE test3 set (timescaledb.compress, timescaledb.compress_orderby='loc,"Time"', timescaledb.compress_chunk_time_interval='2 hours');
WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes
NOTICE: default segment by for hypertable "test3" is set to ""
WARNING: compress_chunk_time_interval configured and primary dimension not first column in compress_orderby
HINT: consider setting "Time" as first compress_orderby column
\set VERBOSITY terse
SELECT
$$
SELECT * FROM test3 WHERE i = 1 ORDER BY "Time"
Expand Down Expand Up @@ -264,10 +272,14 @@ NOTICE: adding not-null constraint to column "Time"
(1 row)

-- Setting compress_chunk_time_interval to non-multiple of chunk_time_interval should emit a warning.
\set VERBOSITY default
ALTER TABLE test4 set (timescaledb.compress, timescaledb.compress_orderby='loc,"Time"', timescaledb.compress_chunk_time_interval='90 minutes');
WARNING: compress chunk interval is not a multiple of chunk interval, you should use a factor of chunk interval to merge as much as possible
WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes
NOTICE: default segment by for hypertable "test4" is set to ""
WARNING: compress_chunk_time_interval configured and primary dimension not first column in compress_orderby
HINT: consider setting "Time" as first compress_orderby column
\set VERBOSITY terse
DROP TABLE test4;
CREATE TABLE test5 ("Time" timestamptz, i integer, value integer);
SELECT table_name from create_hypertable('test5', 'Time', chunk_time_interval=> INTERVAL '1 hour');
Expand Down Expand Up @@ -604,6 +616,7 @@ FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-03 0:59', '1 minut
CROSS JOIN generate_series(1, 5, 1) i;
-- Compression is set to merge those 24 chunks into 12 2 hour chunks with ordering by j column before time column, causing recompression to occur during merge.
ALTER TABLE test7 set (timescaledb.compress, timescaledb.compress_segmentby='i', timescaledb.compress_orderby='j, "Time" desc', timescaledb.compress_chunk_time_interval='2 hours');
WARNING: compress_chunk_time_interval configured and primary dimension not first column in compress_orderby
SELECT
$$
SELECT * FROM test7 ORDER BY i, "Time"
Expand Down
6 changes: 6 additions & 0 deletions tsl/test/sql/compression_merge.sql
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-03 0:59', '1 minut
CROSS JOIN generate_series(1, 5, 1) i;

-- Compression is set to merge those 24 chunks into 3 chunks, two 10 hour chunks and a single 4 hour chunk.
\set VERBOSITY default
ALTER TABLE test2 set (timescaledb.compress, timescaledb.compress_segmentby='i', timescaledb.compress_orderby='loc,"Time"', timescaledb.compress_chunk_time_interval='10 hours');
\set VERBOSITY terse

-- Verify we are fully recompressing unordered chunks
BEGIN;
Expand Down Expand Up @@ -87,7 +89,9 @@ INSERT INTO test3 SELECT t, 2, gen_rand_minstd(), gen_rand_minstd() FROM generat
INSERT INTO test3 SELECT t, 3, gen_rand_minstd(), gen_rand_minstd() FROM generate_series('2018-03-02 2:00'::TIMESTAMPTZ, '2018-03-02 2:01', '1 minute') t;

-- Compression is set to merge those 25 chunks into 12 2 hour chunks and a single 1 hour chunks on a different space dimensions.
\set VERBOSITY default
ALTER TABLE test3 set (timescaledb.compress, timescaledb.compress_orderby='loc,"Time"', timescaledb.compress_chunk_time_interval='2 hours');
\set VERBOSITY terse

SELECT
$$
Expand All @@ -108,7 +112,9 @@ DROP TABLE test3;
CREATE TABLE test4 ("Time" timestamptz, i integer, loc integer, value integer);
SELECT table_name from create_hypertable('test4', 'Time', chunk_time_interval=> INTERVAL '1 hour');
-- Setting compress_chunk_time_interval to non-multiple of chunk_time_interval should emit a warning.
\set VERBOSITY default
ALTER TABLE test4 set (timescaledb.compress, timescaledb.compress_orderby='loc,"Time"', timescaledb.compress_chunk_time_interval='90 minutes');
\set VERBOSITY terse

DROP TABLE test4;

Expand Down

0 comments on commit 9115e12

Please sign in to comment.