Skip to content

Commit

Permalink
Add GUC for segmentwise recompression (#7413)
Browse files Browse the repository at this point in the history
Add GUC option to enable or disable segmentwise recompression. If
disabled, then a full recompression is done instead when recompression
is attempted through `compress_chunk`. If `recompress_chunk_segmentwise`
is used when GUC is disabled, then an error is thrown.

Closes #7381.
  • Loading branch information
kpan2034 authored Nov 4, 2024
1 parent 76e3b27 commit 7c78fad
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 1 deletion.
1 change: 1 addition & 0 deletions .unreleased/pr_7413
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implements: #7413: Add GUC for segmentwise recompression.
12 changes: 12 additions & 0 deletions src/guc.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ TSDLLEXPORT bool ts_guc_enable_compression_indexscan = false;
TSDLLEXPORT bool ts_guc_enable_bulk_decompression = true;
TSDLLEXPORT bool ts_guc_auto_sparse_indexes = true;
bool ts_guc_enable_chunk_skipping = false;
TSDLLEXPORT bool ts_guc_enable_segmentwise_recompression = true;

/* Enable of disable columnar scans for columnar-oriented storage engines. If
* disabled, regular sequence scans will be used instead. */
Expand Down Expand Up @@ -703,6 +704,17 @@ _guc_init(void)
NULL,
NULL);

DefineCustomBoolVariable(MAKE_EXTOPTION("enable_segmentwise_recompression"),
"Enable segmentwise recompression functionality",
"Enable segmentwise recompression",
&ts_guc_enable_segmentwise_recompression,
true,
PGC_USERSET,
0,
NULL,
NULL,
NULL);

/*
* Define the limit on number of invalidation-based refreshes we allow per
* refresh call. If this limit is exceeded, fall back to a single refresh that
Expand Down
1 change: 1 addition & 0 deletions src/guc.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ extern bool ts_guc_enable_tss_callbacks;
extern TSDLLEXPORT bool ts_guc_enable_delete_after_compression;
extern TSDLLEXPORT bool ts_guc_enable_merge_on_cagg_refresh;
extern bool ts_guc_enable_chunk_skipping;
extern TSDLLEXPORT bool ts_guc_enable_segmentwise_recompression;

#ifdef USE_TELEMETRY
typedef enum TelemetryLevel
Expand Down
18 changes: 17 additions & 1 deletion tsl/src/compression/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* compress and decompress chunks
*/
#include <postgres.h>
#include "guc.h"
#include <access/tableam.h>
#include <access/xact.h>
#include <catalog/dependency.h>
Expand Down Expand Up @@ -919,12 +920,19 @@ tsl_compress_chunk_wrapper(Chunk *chunk, bool if_not_compressed, bool recompress
return uncompressed_chunk_id;
}

if (ts_chunk_is_partial(chunk) && get_compressed_chunk_index_for_recompression(chunk))
if (ts_guc_enable_segmentwise_recompression && ts_chunk_is_partial(chunk) &&
get_compressed_chunk_index_for_recompression(chunk))
{
uncompressed_chunk_id = recompress_chunk_segmentwise_impl(chunk);
}
else
{
if (!ts_guc_enable_segmentwise_recompression)
elog(NOTICE,
"segmentwise recompression is disabled, performing full recompression on "
"chunk \"%s.%s\"",
NameStr(chunk->fd.schema_name),
NameStr(chunk->fd.table_name));
decompress_chunk_impl(chunk, false);
compress_chunk_impl(chunk->hypertable_relid, chunk->table_id);
}
Expand Down Expand Up @@ -1257,6 +1265,14 @@ tsl_recompress_chunk_segmentwise(PG_FUNCTION_ARGS)
}
else
{
if (!ts_guc_enable_segmentwise_recompression)
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("segmentwise recompression functionality disabled, "
"enable it by first setting "
"timescaledb.enable_segmentwise_recompression to on")));
}
uncompressed_chunk_id = recompress_chunk_segmentwise_impl(chunk);
}

Expand Down
33 changes: 33 additions & 0 deletions tsl/test/expected/recompress_chunk_segmentwise.out
Original file line number Diff line number Diff line change
Expand Up @@ -593,3 +593,36 @@ select * from :compressed_chunk_name;
2 | 1 | | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST | BAAAAneAR/JEAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAA7gAE7wCP5IgAAATvAI/kh/8= | BAEAAAAAAAAABAAAAAAAAAAEAAAAAQAAAAEAAAAAAAAABAAAAAAAAAAIAAAAAgAAAAEAAAAAAAAAAQAAAAAAAAAB
(5 rows)

--- Test behaviour when enable_segmentwise_recompression GUC if OFF
CREATE TABLE guc_test(time timestamptz not null, a int, b int, c int);
SELECT create_hypertable('guc_test', by_range('time', INTERVAL '1 day'));
create_hypertable
-------------------
(18,t)
(1 row)

ALTER TABLE guc_test set (timescaledb.compress, timescaledb.compress_segmentby = 'a, b');
NOTICE: default order by for hypertable "guc_test" is set to ""time" DESC"
INSERT INTO guc_test VALUES ('2024-10-30 14:04:00.501519-06'::timestamptz, 1, 1, 1);
SELECT show_chunks as chunk_to_compress FROM show_chunks('guc_test') LIMIT 1 \gset
SELECT compress_chunk(:'chunk_to_compress');
compress_chunk
------------------------------------------
_timescaledb_internal._hyper_18_20_chunk
(1 row)

INSERT INTO guc_test VALUES ('2024-10-30 14:14:00.501519-06'::timestamptz, 1, 1, 2);
-- When GUC is OFF, recompress function should throw an error
SET timescaledb.enable_segmentwise_recompression TO OFF;
\set ON_ERROR_STOP 0
SELECT _timescaledb_functions.recompress_chunk_segmentwise(:'chunk_to_compress');
ERROR: segmentwise recompression functionality disabled, enable it by first setting timescaledb.enable_segmentwise_recompression to on
\set ON_ERROR_STOP 1
-- When GUC is OFF, entire chunk should be fully uncompressed and compressed instead
SELECT compress_chunk(:'chunk_to_compress');
NOTICE: segmentwise recompression is disabled, performing full recompression on chunk "_timescaledb_internal._hyper_18_20_chunk"
compress_chunk
------------------------------------------
_timescaledb_internal._hyper_18_20_chunk
(1 row)

18 changes: 18 additions & 0 deletions tsl/test/sql/recompress_chunk_segmentwise.sql
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,21 @@ select * from :compressed_chunk_name;
insert into nullseg_many values (:'start_time', 1, NULL, NULL);
SELECT compress_chunk(:'chunk_to_compress');
select * from :compressed_chunk_name;

--- Test behaviour when enable_segmentwise_recompression GUC if OFF
CREATE TABLE guc_test(time timestamptz not null, a int, b int, c int);
SELECT create_hypertable('guc_test', by_range('time', INTERVAL '1 day'));

ALTER TABLE guc_test set (timescaledb.compress, timescaledb.compress_segmentby = 'a, b');
INSERT INTO guc_test VALUES ('2024-10-30 14:04:00.501519-06'::timestamptz, 1, 1, 1);
SELECT show_chunks as chunk_to_compress FROM show_chunks('guc_test') LIMIT 1 \gset
SELECT compress_chunk(:'chunk_to_compress');

INSERT INTO guc_test VALUES ('2024-10-30 14:14:00.501519-06'::timestamptz, 1, 1, 2);
-- When GUC is OFF, recompress function should throw an error
SET timescaledb.enable_segmentwise_recompression TO OFF;
\set ON_ERROR_STOP 0
SELECT _timescaledb_functions.recompress_chunk_segmentwise(:'chunk_to_compress');
\set ON_ERROR_STOP 1
-- When GUC is OFF, entire chunk should be fully uncompressed and compressed instead
SELECT compress_chunk(:'chunk_to_compress');

0 comments on commit 7c78fad

Please sign in to comment.