Make compressed chunks use same tablespace as uncompressed

For tablepaces with compressed chunks the semantics are the following:
  - compressed chunks get put into the same tablespace as the
    uncommpressed chunk on compression.
 - set tablespace on uncompressed hypertable cascades to compressed hypertable+chunks
 - set tablespace on all chunks is blocked (same as w/o compression)
 - move chunks on a uncompressed chunk errors
 - move chunks on compressed chunk works

In the future we will:
 - add tablespace option to compress_chunk function and policy (this will override the setting
   of the uncompressed chunk). This will allow changing tablespaces upon compression
 - Note: The current plan is to never listen to the setting on compressed hypertable. In fact,
   we will block setting tablespace on  compressed hypertables
This commit is contained in:
Matvey Arye 2019-10-03 17:59:29 -04:00 committed by Matvey Arye
parent 4d65a01a57
commit b8a98c1f18
6 changed files with 166 additions and 9 deletions

View File

@ -580,7 +580,7 @@ create_toast_table(CreateStmt *stmt, Oid chunk_oid)
* instead needs the proper permissions on the database to create the schema.
*/
Oid
ts_chunk_create_table(Chunk *chunk, Hypertable *ht)
ts_chunk_create_table(Chunk *chunk, Hypertable *ht, char *tablespacename)
{
Relation rel;
ObjectAddress objaddr;
@ -590,7 +590,7 @@ ts_chunk_create_table(Chunk *chunk, Hypertable *ht)
.relation = makeRangeVar(NameStr(chunk->fd.schema_name), NameStr(chunk->fd.table_name), 0),
.inhRelations =
list_make1(makeRangeVar(NameStr(ht->fd.schema_name), NameStr(ht->fd.table_name), 0)),
.tablespacename = ts_hypertable_select_tablespace_name(ht, chunk),
.tablespacename = tablespacename,
.options = get_reloptions(ht->main_table_relid),
};
Oid uid, saved_uid;
@ -679,7 +679,8 @@ chunk_create_after_lock(Hypertable *ht, Point *p, const char *schema, const char
ts_chunk_add_constraints(chunk);
/* Create the actual table relation for the chunk */
chunk->table_id = ts_chunk_create_table(chunk, ht);
chunk->table_id =
ts_chunk_create_table(chunk, ht, ts_hypertable_select_tablespace_name(ht, chunk));
if (!OidIsValid(chunk->table_id))
elog(ERROR, "could not create chunk table");

View File

@ -95,7 +95,7 @@ extern Chunk *ts_chunk_get_by_name_with_memory_context(const char *schema_name,
bool fail_if_not_found);
extern TSDLLEXPORT void ts_chunk_insert_lock(Chunk *chunk, LOCKMODE lock);
extern TSDLLEXPORT Oid ts_chunk_create_table(Chunk *chunk, Hypertable *ht);
extern TSDLLEXPORT Oid ts_chunk_create_table(Chunk *chunk, Hypertable *ht, char *tablespacename);
extern TSDLLEXPORT Chunk *ts_chunk_get_by_id(int32 id, int16 num_constraints,
bool fail_if_not_found);
extern TSDLLEXPORT Chunk *ts_chunk_get_by_relid(Oid relid, int16 num_constraints,

View File

@ -562,6 +562,8 @@ create_compress_chunk_table(Hypertable *compress_ht, Chunk *src_chunk)
NameStr(compress_ht->fd.associated_table_prefix),
compress_chunk->fd.id);
;
/* Insert chunk */
ts_chunk_insert_lock(compress_chunk, RowExclusiveLock);
@ -570,8 +572,15 @@ create_compress_chunk_table(Hypertable *compress_ht, Chunk *src_chunk)
compress_chunk->fd.id,
compress_chunk->hypertable_relid);
/* Create the actual table relation for the chunk */
compress_chunk->table_id = ts_chunk_create_table(compress_chunk, compress_ht);
/* Create the actual table relation for the chunk
* Note that we have to pick the tablespace here as the compressed ht doesn't have dimensions
* on which to base this decision. We simply pick the same tablespace as the uncompressed chunk
* for now.
*/
compress_chunk->table_id =
ts_chunk_create_table(compress_chunk,
compress_ht,
get_tablespace_name(get_rel_tablespace(src_chunk->table_id)));
if (!OidIsValid(compress_chunk->table_id))
elog(ERROR, "could not create compress chunk table");

View File

@ -174,6 +174,11 @@ reorder_chunk(Oid chunk_id, Oid index_id, bool verbose, Oid wait_id, Oid destina
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" is not a chunk", get_rel_name(chunk_id))));
if (chunk->fd.compressed_chunk_id != INVALID_CHUNK_ID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" is a compressed chunk", get_rel_name(chunk_id))));
hcache = ts_hypertable_cache_pin();
ht = ts_hypertable_cache_get_entry(hcache, chunk->hypertable_relid);
if (NULL == ht)

View File

@ -44,7 +44,8 @@ NOTICE: adding not-null constraint to column "Time"
(1 row)
INSERT INTO test1 SELECT t, gen_rand_minstd(), gen_rand_minstd(), gen_rand_minstd()::text FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '1 hour') t;
ALTER TABLE test1 set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = '"Time" DESC');
ALTER TABLE test1 set (timescaledb.compress, timescaledb.compress_segmentby = 'b', timescaledb.compress_orderby = '"Time" DESC');
NOTICE: adding index _compressed_hypertable_2_b__ts_meta_sequence_num_idx ON _timescaledb_internal._compressed_hypertable_2 USING BTREE(b, _ts_meta_sequence_num)
SELECT COUNT(*) AS count_compressed
FROM
(
@ -67,6 +68,19 @@ DROP INDEX new_index;
ALTER TABLE test1 SET (fillfactor=100);
ALTER TABLE test1 RESET (fillfactor);
ALTER TABLE test1 ALTER COLUMN b SET STATISTICS 10;
-- TABLESPACES
-- For tablepaces with compressed chunks the semantics are the following:
-- - compressed chunks get put into the same tablespace as the
-- uncommpressed chunk on compression.
-- - set tablespace on uncompressed hypertable cascades to compressed hypertable+chunks
-- - set tablespace on all chunks is blocked (same as w/o compression)
-- - move chunks on a uncompressed chunk errors
-- - move chunks on compressed chunk works
--In the future we will:
-- - add tablespace option to compress_chunk function and policy (this will override the setting
-- of the uncompressed chunk). This will allow changing tablespaces upon compression
-- - Note: The current plan is to never listen to the setting on compressed hypertable. In fact,
-- we will block setting tablespace on compressed hypertables
SELECT count(*) as "COUNT_CHUNKS_UNCOMPRESSED"
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)
@ -93,6 +107,79 @@ FROM pg_tables WHERE tablespace = 'tablespace2';
t
(1 row)
SELECT
comp_chunk.schema_name|| '.' || comp_chunk.table_name as "COMPRESSED_CHUNK_NAME",
uncomp_chunk.schema_name|| '.' || uncomp_chunk.table_name as "UNCOMPRESSED_CHUNK_NAME"
FROM _timescaledb_catalog.chunk comp_chunk
INNER JOIN _timescaledb_catalog.hypertable comp_hyper ON (comp_chunk.hypertable_id = comp_hyper.id)
INNER JOIN _timescaledb_catalog.hypertable uncomp_hyper ON (comp_hyper.id = uncomp_hyper.compressed_hypertable_id)
INNER JOIN _timescaledb_catalog.chunk uncomp_chunk ON (uncomp_chunk.compressed_chunk_id = comp_chunk.id)
WHERE uncomp_hyper.table_name like 'test1' ORDER BY comp_chunk.id LIMIT 1\gset
\set ON_ERROR_STOP 0
--set tablespace is blocked on chunks for now; if this ever changes we need
--to test that path to make sure it passes down the tablespace.
ALTER TABLE :UNCOMPRESSED_CHUNK_NAME SET TABLESPACE tablespace1;
ERROR: operation not supported on chunk tables
SELECT move_chunk(chunk=>:'UNCOMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."_hyper_1_1_chunk_test1_Time_idx"');
WARNING: Timescale License expired
ERROR: "_hyper_1_1_chunk" is a compressed chunk
\set ON_ERROR_STOP 1
SELECT move_chunk(chunk=>:'COMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."compress_hyper_2_28_chunk__compressed_hypertable_2_b__ts_meta_s"');
move_chunk
------------
(1 row)
-- the compressed chunk is in here now
SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
count
-------
1
(1 row)
SELECT decompress_chunk(:'UNCOMPRESSED_CHUNK_NAME');
decompress_chunk
------------------
(1 row)
--the compresse chunk was dropped by decompression
SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
count
-------
0
(1 row)
SELECT move_chunk(chunk=>:'UNCOMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."_hyper_1_1_chunk_test1_Time_idx"');
move_chunk
------------
(1 row)
--the uncompressed chunks has now been moved
SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
count
-------
1
(1 row)
SELECT compress_chunk(:'UNCOMPRESSED_CHUNK_NAME');
compress_chunk
----------------
(1 row)
--the compressed chunk is now in the same tablespace as the uncompressed one
SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
count
-------
2
(1 row)
--
-- DROP CHUNKS
--

View File

@ -22,8 +22,7 @@ SELECT table_name from create_hypertable('test1', 'Time', chunk_time_interval=>
INSERT INTO test1 SELECT t, gen_rand_minstd(), gen_rand_minstd(), gen_rand_minstd()::text FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '1 hour') t;
ALTER TABLE test1 set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = '"Time" DESC');
ALTER TABLE test1 set (timescaledb.compress, timescaledb.compress_segmentby = 'b', timescaledb.compress_orderby = '"Time" DESC');
SELECT COUNT(*) AS count_compressed
FROM
@ -46,6 +45,22 @@ ALTER TABLE test1 RESET (fillfactor);
ALTER TABLE test1 ALTER COLUMN b SET STATISTICS 10;
-- TABLESPACES
-- For tablepaces with compressed chunks the semantics are the following:
-- - compressed chunks get put into the same tablespace as the
-- uncommpressed chunk on compression.
-- - set tablespace on uncompressed hypertable cascades to compressed hypertable+chunks
-- - set tablespace on all chunks is blocked (same as w/o compression)
-- - move chunks on a uncompressed chunk errors
-- - move chunks on compressed chunk works
--In the future we will:
-- - add tablespace option to compress_chunk function and policy (this will override the setting
-- of the uncompressed chunk). This will allow changing tablespaces upon compression
-- - Note: The current plan is to never listen to the setting on compressed hypertable. In fact,
-- we will block setting tablespace on compressed hypertables
SELECT count(*) as "COUNT_CHUNKS_UNCOMPRESSED"
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)
@ -67,6 +82,46 @@ ALTER TABLE test1 SET TABLESPACE tablespace2;
SELECT count(*) = (:COUNT_CHUNKS_UNCOMPRESSED +:COUNT_CHUNKS_COMPRESSED + 2)
FROM pg_tables WHERE tablespace = 'tablespace2';
SELECT
comp_chunk.schema_name|| '.' || comp_chunk.table_name as "COMPRESSED_CHUNK_NAME",
uncomp_chunk.schema_name|| '.' || uncomp_chunk.table_name as "UNCOMPRESSED_CHUNK_NAME"
FROM _timescaledb_catalog.chunk comp_chunk
INNER JOIN _timescaledb_catalog.hypertable comp_hyper ON (comp_chunk.hypertable_id = comp_hyper.id)
INNER JOIN _timescaledb_catalog.hypertable uncomp_hyper ON (comp_hyper.id = uncomp_hyper.compressed_hypertable_id)
INNER JOIN _timescaledb_catalog.chunk uncomp_chunk ON (uncomp_chunk.compressed_chunk_id = comp_chunk.id)
WHERE uncomp_hyper.table_name like 'test1' ORDER BY comp_chunk.id LIMIT 1\gset
\set ON_ERROR_STOP 0
--set tablespace is blocked on chunks for now; if this ever changes we need
--to test that path to make sure it passes down the tablespace.
ALTER TABLE :UNCOMPRESSED_CHUNK_NAME SET TABLESPACE tablespace1;
SELECT move_chunk(chunk=>:'UNCOMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."_hyper_1_1_chunk_test1_Time_idx"');
\set ON_ERROR_STOP 1
SELECT move_chunk(chunk=>:'COMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."compress_hyper_2_28_chunk__compressed_hypertable_2_b__ts_meta_s"');
-- the compressed chunk is in here now
SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
SELECT decompress_chunk(:'UNCOMPRESSED_CHUNK_NAME');
--the compresse chunk was dropped by decompression
SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
SELECT move_chunk(chunk=>:'UNCOMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."_hyper_1_1_chunk_test1_Time_idx"');
--the uncompressed chunks has now been moved
SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
SELECT compress_chunk(:'UNCOMPRESSED_CHUNK_NAME');
--the compressed chunk is now in the same tablespace as the uncompressed one
SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
--