mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-15 01:53:41 +08:00
Add ability to turn off compression
Since enabling compression creates limits on the hypertable (e.g. types of constraints allowed) even if there are no compressed chunks, we add the ability to turn off compression. This is only possible if there are no compressed chunks.
This commit is contained in:
parent
887d0271e8
commit
85d30e404d
@ -2032,55 +2032,22 @@ ts_hypertable_set_integer_now_func(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
static ScanTupleResult
|
||||
hypertable_set_compressed_id_in_tuple(TupleInfo *ti, void *data)
|
||||
{
|
||||
bool nulls[Natts_hypertable];
|
||||
Datum values[Natts_hypertable];
|
||||
bool repl[Natts_hypertable] = { false };
|
||||
CatalogSecurityContext sec_ctx;
|
||||
|
||||
HeapTuple tuple;
|
||||
int32 compressed_hypertable_id = *((int32 *) data);
|
||||
|
||||
heap_deform_tuple(ti->tuple, ti->desc, values, nulls);
|
||||
|
||||
Assert(DatumGetBool(values[AttrNumberGetAttrOffset(Anum_hypertable_compressed)]) == false);
|
||||
nulls[AttrNumberGetAttrOffset(Anum_hypertable_compressed_hypertable_id)] = false;
|
||||
values[AttrNumberGetAttrOffset(Anum_hypertable_compressed_hypertable_id)] =
|
||||
Int32GetDatum(compressed_hypertable_id);
|
||||
|
||||
repl[AttrNumberGetAttrOffset(Anum_hypertable_compressed_hypertable_id)] = true;
|
||||
ts_catalog_database_info_become_owner(ts_catalog_database_info_get(), &sec_ctx);
|
||||
tuple = heap_modify_tuple(ti->tuple, ti->desc, values, nulls, repl);
|
||||
ts_catalog_update(ti->scanrel, tuple);
|
||||
heap_freetuple(tuple);
|
||||
ts_catalog_restore_user(&sec_ctx);
|
||||
|
||||
return SCAN_DONE;
|
||||
}
|
||||
|
||||
/*Assume permissions are already checked */
|
||||
bool
|
||||
ts_hypertable_set_compressed_id(Hypertable *ht, int32 compressed_hypertable_id)
|
||||
{
|
||||
int32 compress_id;
|
||||
ScanKeyData scankey[1];
|
||||
ScanKeyInit(&scankey[0],
|
||||
Anum_hypertable_pkey_idx_id,
|
||||
BTEqualStrategyNumber,
|
||||
F_INT4EQ,
|
||||
Int32GetDatum(ht->fd.id));
|
||||
compress_id = compressed_hypertable_id;
|
||||
return hypertable_scan_limit_internal(scankey,
|
||||
1,
|
||||
HYPERTABLE_ID_INDEX,
|
||||
hypertable_set_compressed_id_in_tuple,
|
||||
&compress_id,
|
||||
1,
|
||||
RowExclusiveLock,
|
||||
false,
|
||||
CurrentMemoryContext) > 0;
|
||||
Assert(!ht->fd.compressed);
|
||||
ht->fd.compressed_hypertable_id = compressed_hypertable_id;
|
||||
return ts_hypertable_update(ht) > 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ts_hypertable_unset_compressed_id(Hypertable *ht)
|
||||
{
|
||||
Assert(!ht->fd.compressed);
|
||||
ht->fd.compressed_hypertable_id = INVALID_HYPERTABLE_ID;
|
||||
return ts_hypertable_update(ht) > 0;
|
||||
}
|
||||
|
||||
/* create a compressed hypertable
|
||||
|
@ -112,6 +112,7 @@ extern List *ts_hypertable_get_all_by_name(Name schema_name, Name table_name, Me
|
||||
extern bool ts_is_partitioning_column(Hypertable *ht, Index column_attno);
|
||||
extern TSDLLEXPORT bool ts_hypertable_set_compressed_id(Hypertable *ht,
|
||||
int32 compressed_hypertable_id);
|
||||
extern TSDLLEXPORT bool ts_hypertable_unset_compressed_id(Hypertable *ht);
|
||||
extern TSDLLEXPORT bool ts_hypertable_is_compressed_internal(int32 compressed_hypertable_id);
|
||||
extern TSDLLEXPORT void ts_hypertable_clone_constraints_to_compressed(Hypertable *ht,
|
||||
List *constraint_list);
|
||||
|
@ -811,12 +811,16 @@ tsl_process_compress_table(AlterTableCmd *cmd, Hypertable *ht,
|
||||
|
||||
if (!compress_enable)
|
||||
{
|
||||
if (compression_already_enabled)
|
||||
if (!with_clause_options[CompressOrderBy].is_default ||
|
||||
!with_clause_options[CompressSegmentBy].is_default)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("disabling compression is not yet supported")));
|
||||
/* compression is not enabled, so just return */
|
||||
return false;
|
||||
errmsg(
|
||||
"cannot set additional compression options when disabling compression")));
|
||||
|
||||
if (!compression_already_enabled)
|
||||
/* compression is not enabled, so just return */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (compressed_chunks_exist)
|
||||
@ -828,7 +832,7 @@ tsl_process_compress_table(AlterTableCmd *cmd, Hypertable *ht,
|
||||
/* Require both order by and segment by when altering if they were previously set because
|
||||
* otherwise it's not clear what the default value means: does it mean leave as-is or is it an
|
||||
* empty list. */
|
||||
if (compression_already_enabled)
|
||||
if (compress_enable && compression_already_enabled)
|
||||
{
|
||||
List *info = ts_hypertable_compression_get(ht->fd.id);
|
||||
ListCell *lc;
|
||||
@ -869,7 +873,7 @@ tsl_process_compress_table(AlterTableCmd *cmd, Hypertable *ht,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("compression cannot be used on table with row security")));
|
||||
|
||||
if (compression_already_enabled)
|
||||
if (compression_already_enabled || !compress_enable)
|
||||
{
|
||||
Hypertable *compressed = ts_hypertable_get_by_id(ht->fd.compressed_hypertable_id);
|
||||
if (compressed == NULL)
|
||||
@ -880,6 +884,12 @@ tsl_process_compress_table(AlterTableCmd *cmd, Hypertable *ht,
|
||||
ts_hypertable_compression_delete_by_hypertable_id(ht->fd.id);
|
||||
}
|
||||
|
||||
if (!compress_enable)
|
||||
{
|
||||
ts_hypertable_unset_compressed_id(ht);
|
||||
return true;
|
||||
}
|
||||
|
||||
compress_htid = create_compression_table(ownerid, &compress_cols);
|
||||
ts_hypertable_set_compressed_id(ht, compress_htid);
|
||||
|
||||
|
@ -477,6 +477,71 @@ SELECT a.rolname from pg_class c INNER JOIN pg_authid a ON(c.relowner = a.oid) W
|
||||
default_perm_user_2
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- turn off compression
|
||||
--
|
||||
SELECT COUNT(*) AS count_compressed
|
||||
FROM
|
||||
(
|
||||
SELECT decompress_chunk(chunk.schema_name|| '.' || chunk.table_name)
|
||||
FROM _timescaledb_catalog.chunk chunk
|
||||
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)
|
||||
WHERE hypertable.table_name like 'test1' and chunk.compressed_chunk_id IS NOT NULL ORDER BY chunk.id
|
||||
)
|
||||
AS sub;
|
||||
count_compressed
|
||||
------------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
ALTER table test1 set (timescaledb.compress='f');
|
||||
--only one hypertable left
|
||||
SELECT count(*) = 1 FROM _timescaledb_catalog.hypertable hypertable;
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT compressed_hypertable_id IS NULL FROM _timescaledb_catalog.hypertable hypertable WHERE hypertable.table_name like 'test1' ;
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
--no hypertable compression entries left
|
||||
SELECT count(*) = 0 FROM _timescaledb_catalog.hypertable_compression;
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
--make sure there are no orphaned _timescaledb_catalog.compression_chunk_size entries (should be 0)
|
||||
SELECT count(*) as orphaned_compression_chunk_size
|
||||
FROM _timescaledb_catalog.compression_chunk_size size
|
||||
LEFT JOIN _timescaledb_catalog.chunk chunk ON (chunk.id = size.chunk_id)
|
||||
WHERE chunk.id IS NULL;
|
||||
orphaned_compression_chunk_size
|
||||
---------------------------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
--can turn compression back on
|
||||
ALTER TABLE test1 set (timescaledb.compress, timescaledb.compress_segmentby = 'b', timescaledb.compress_orderby = '"Time" DESC');
|
||||
NOTICE: adding index _compressed_hypertable_3_b__ts_meta_sequence_num_idx ON _timescaledb_internal._compressed_hypertable_3 USING BTREE(b, _ts_meta_sequence_num)
|
||||
SELECT COUNT(*) AS count_compressed
|
||||
FROM
|
||||
(
|
||||
SELECT compress_chunk(chunk.schema_name|| '.' || chunk.table_name)
|
||||
FROM _timescaledb_catalog.chunk chunk
|
||||
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)
|
||||
WHERE hypertable.table_name like 'test1' and chunk.compressed_chunk_id IS NULL ORDER BY chunk.id
|
||||
)
|
||||
AS sub;
|
||||
count_compressed
|
||||
------------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
DROP TABLE test1;
|
||||
DROP TABLESPACE tablespace1;
|
||||
DROP TABLESPACE tablespace2;
|
||||
|
@ -79,8 +79,6 @@ NOTICE: adding index _compressed_hypertable_10_c__ts_meta_sequence_num_idx ON _
|
||||
-- Negative test cases ---
|
||||
ALTER TABLE foo2 set (timescaledb.compress, timescaledb.compress_segmentby = '"bacB toD",c');
|
||||
ERROR: need to specify compress_orderby if it was previously set
|
||||
ALTER TABLE foo2 set (timescaledb.compress='f');
|
||||
ERROR: disabling compression is not yet supported
|
||||
create table reserved_column_prefix (a integer, _ts_meta_foo integer, "bacB toD" integer, c integer, d integer);
|
||||
select table_name from create_hypertable('reserved_column_prefix', 'a', chunk_time_interval=> 10);
|
||||
NOTICE: adding not-null constraint to column "a"
|
||||
@ -229,6 +227,10 @@ FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht where ch
|
||||
ERROR: chunks can be compressed only if compression property is set on the hypertable
|
||||
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a', timescaledb.compress_segmentby = 'c');
|
||||
ERROR: cannot change compression options as compressed chunks already exist for this table
|
||||
ALTER TABLE foo set (timescaledb.compress='f');
|
||||
ERROR: cannot change compression options as compressed chunks already exist for this table
|
||||
ALTER TABLE foo reset (timescaledb.compress);
|
||||
ERROR: compression options cannot be reset
|
||||
select decompress_chunk(ch1.schema_name|| '.' || ch1.table_name)
|
||||
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht where ch1.hypertable_id = ht.id and ht.table_name like 'non_compressed' ORDER BY ch1.id limit 1;
|
||||
ERROR: missing compressed hypertable
|
||||
|
@ -332,6 +332,49 @@ SELECT a.rolname from pg_class c INNER JOIN pg_authid a ON(c.relowner = a.oid) W
|
||||
SELECT a.rolname from pg_class c INNER JOIN pg_authid a ON(c.relowner = a.oid) WHERE c.oid = :'COMPRESSED_HYPER_NAME'::regclass;
|
||||
SELECT a.rolname from pg_class c INNER JOIN pg_authid a ON(c.relowner = a.oid) WHERE c.oid = :'COMPRESSED_CHUNK_NAME'::regclass;
|
||||
|
||||
--
|
||||
-- turn off compression
|
||||
--
|
||||
|
||||
SELECT COUNT(*) AS count_compressed
|
||||
FROM
|
||||
(
|
||||
SELECT decompress_chunk(chunk.schema_name|| '.' || chunk.table_name)
|
||||
FROM _timescaledb_catalog.chunk chunk
|
||||
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)
|
||||
WHERE hypertable.table_name like 'test1' and chunk.compressed_chunk_id IS NOT NULL ORDER BY chunk.id
|
||||
)
|
||||
AS sub;
|
||||
|
||||
ALTER table test1 set (timescaledb.compress='f');
|
||||
|
||||
--only one hypertable left
|
||||
SELECT count(*) = 1 FROM _timescaledb_catalog.hypertable hypertable;
|
||||
SELECT compressed_hypertable_id IS NULL FROM _timescaledb_catalog.hypertable hypertable WHERE hypertable.table_name like 'test1' ;
|
||||
--no hypertable compression entries left
|
||||
SELECT count(*) = 0 FROM _timescaledb_catalog.hypertable_compression;
|
||||
--make sure there are no orphaned _timescaledb_catalog.compression_chunk_size entries (should be 0)
|
||||
SELECT count(*) as orphaned_compression_chunk_size
|
||||
FROM _timescaledb_catalog.compression_chunk_size size
|
||||
LEFT JOIN _timescaledb_catalog.chunk chunk ON (chunk.id = size.chunk_id)
|
||||
WHERE chunk.id IS NULL;
|
||||
|
||||
|
||||
--can turn compression back on
|
||||
ALTER TABLE test1 set (timescaledb.compress, timescaledb.compress_segmentby = 'b', timescaledb.compress_orderby = '"Time" DESC');
|
||||
|
||||
SELECT COUNT(*) AS count_compressed
|
||||
FROM
|
||||
(
|
||||
SELECT compress_chunk(chunk.schema_name|| '.' || chunk.table_name)
|
||||
FROM _timescaledb_catalog.chunk chunk
|
||||
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)
|
||||
WHERE hypertable.table_name like 'test1' and chunk.compressed_chunk_id IS NULL ORDER BY chunk.id
|
||||
)
|
||||
AS sub;
|
||||
|
||||
|
||||
|
||||
DROP TABLE test1;
|
||||
DROP TABLESPACE tablespace1;
|
||||
DROP TABLESPACE tablespace2;
|
||||
|
@ -41,7 +41,6 @@ ALTER TABLE foo3 set (timescaledb.compress, timescaledb.compress_segmentby = '"b
|
||||
-- Negative test cases ---
|
||||
|
||||
ALTER TABLE foo2 set (timescaledb.compress, timescaledb.compress_segmentby = '"bacB toD",c');
|
||||
ALTER TABLE foo2 set (timescaledb.compress='f');
|
||||
|
||||
|
||||
create table reserved_column_prefix (a integer, _ts_meta_foo integer, "bacB toD" integer, c integer, d integer);
|
||||
@ -127,6 +126,8 @@ select compress_chunk(ch1.schema_name|| '.' || ch1.table_name)
|
||||
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht where ch1.hypertable_id = ht.id and ht.table_name like 'non_compressed' ORDER BY ch1.id limit 1;
|
||||
|
||||
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a', timescaledb.compress_segmentby = 'c');
|
||||
ALTER TABLE foo set (timescaledb.compress='f');
|
||||
ALTER TABLE foo reset (timescaledb.compress);
|
||||
|
||||
select decompress_chunk(ch1.schema_name|| '.' || ch1.table_name)
|
||||
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht where ch1.hypertable_id = ht.id and ht.table_name like 'non_compressed' ORDER BY ch1.id limit 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user