mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-14 17:43:34 +08:00
This patch introduces a C-function to perform the recompression at a finer granularity instead of decompressing and subsequently compressing the entire chunk. This improves performance for the following reasons: - it needs to sort less data at a time and - it avoids recreating the decompressed chunk and the heap inserts associated with that by decompressing each segment into a tuplesort instead. If no segmentby is specified when enabling compression or if an index does not exist on the compressed chunk then the operation is performed as before, decompressing and subsequently compressing the entire chunk.
506 lines
34 KiB
Plaintext
506 lines
34 KiB
Plaintext
-- This file and its contents are licensed under the Timescale License.
|
|
-- Please see the included NOTICE for copyright information and
|
|
-- LICENSE-TIMESCALE for a copy of the license.
|
|
\c :TEST_DBNAME :ROLE_SUPERUSER
|
|
CREATE OR REPLACE VIEW compressed_chunk_info_view AS
|
|
SELECT
|
|
h.schema_name AS hypertable_schema,
|
|
h.table_name AS hypertable_name,
|
|
c.schema_name as chunk_schema,
|
|
c.table_name as chunk_name,
|
|
c.status as chunk_status,
|
|
comp.schema_name as compressed_chunk_schema,
|
|
comp.table_name as compressed_chunk_name,
|
|
c.id as chunk_id
|
|
FROM
|
|
_timescaledb_catalog.hypertable h JOIN
|
|
_timescaledb_catalog.chunk c ON h.id = c.hypertable_id
|
|
LEFT JOIN _timescaledb_catalog.chunk comp
|
|
ON comp.id = c.compressed_chunk_id
|
|
;
|
|
CREATE OR REPLACE VIEW compression_rowcnt_view AS
|
|
select ccs.numrows_pre_compression, ccs.numrows_post_compression,
|
|
(v.chunk_schema || '.' || v.chunk_name) as chunk_name,
|
|
v.chunk_id as chunk_id
|
|
from _timescaledb_catalog.compression_chunk_size ccs
|
|
join compressed_chunk_info_view v on ccs.chunk_id = v.chunk_id;
|
|
------------- only one segment exists and only one segment affected ---------
|
|
create table mytab_oneseg (time timestamptz not null, a int, b int, c int);
|
|
SELECT create_hypertable('mytab_oneseg', 'time', chunk_time_interval => interval '1 day');
|
|
create_hypertable
|
|
---------------------------
|
|
(1,public,mytab_oneseg,t)
|
|
(1 row)
|
|
|
|
insert into mytab_oneseg values
|
|
('2023-01-01 21:56:20.048355+02'::timestamptz, 2, NULL, 2),
|
|
('2023-01-01 21:56:10.048355+02'::timestamptz, 2, NULL, 2); --same chunk same segment
|
|
alter table mytab_oneseg set (timescaledb.compress, timescaledb.compress_segmentby = 'a, c');
|
|
select show_chunks as chunk_to_compress_1 from show_chunks('mytab_oneseg') limit 1 \gset
|
|
select compress_chunk(:'chunk_to_compress_1');
|
|
compress_chunk
|
|
----------------------------------------
|
|
_timescaledb_internal._hyper_1_1_chunk
|
|
(1 row)
|
|
|
|
SELECT compressed_chunk_schema || '.' || compressed_chunk_name as compressed_chunk_name_1
|
|
from compressed_chunk_info_view where hypertable_name = 'mytab_oneseg' \gset
|
|
SELECT ctid, * FROM :compressed_chunk_name_1;
|
|
ctid | time | a | b | c | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
-------+----------------------------------------------------------------------+---+---+---+----------------+-----------------------+-------------------------------------+-------------------------------------
|
|
(0,1) | BAAAApQ3/qlnY///////Z2mAAAAAAgAAAAIAAAAAAAAA7gAFKG/+g/vGAAUob/+1KMU= | 2 | | 2 | 2 | 10 | Sun Jan 01 11:56:10.048355 2023 PST | Sun Jan 01 11:56:20.048355 2023 PST
|
|
(1 row)
|
|
|
|
-- after compressing the chunk
|
|
select numrows_pre_compression, numrows_post_compression from _timescaledb_catalog.compression_chunk_size;
|
|
numrows_pre_compression | numrows_post_compression
|
|
-------------------------+--------------------------
|
|
2 | 1
|
|
(1 row)
|
|
|
|
insert into mytab_oneseg values ('2023-01-01 19:56:20.048355+02'::timestamptz, 2, NULL, 2);
|
|
-- after inserting new row in compressed chunk
|
|
select numrows_pre_compression, numrows_post_compression from _timescaledb_catalog.compression_chunk_size;
|
|
numrows_pre_compression | numrows_post_compression
|
|
-------------------------+--------------------------
|
|
2 | 1
|
|
(1 row)
|
|
|
|
select _timescaledb_internal.recompress_chunk_segmentwise(:'chunk_to_compress_1');
|
|
recompress_chunk_segmentwise
|
|
----------------------------------------
|
|
_timescaledb_internal._hyper_1_1_chunk
|
|
(1 row)
|
|
|
|
-- check the ctid of the rows in the recompressed chunk to verify that we've written new data
|
|
SELECT ctid, * FROM :compressed_chunk_name_1;
|
|
ctid | time | a | b | c | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
-------+----------------------------------------------------------------------------------+---+---+---+----------------+-----------------------+-------------------------------------+-------------------------------------
|
|
(0,2) | BAAAApQ2Uhq14/////5TcU6AAAAAAwAAAAMAAAAAAAAO7gAFKG/+g/vGAAUob/+1KMUAAAADV+w1/w== | 2 | | 2 | 3 | 10 | Sun Jan 01 09:56:20.048355 2023 PST | Sun Jan 01 11:56:20.048355 2023 PST
|
|
(1 row)
|
|
|
|
-- after recompressing chunk
|
|
select numrows_pre_compression, numrows_post_compression from _timescaledb_catalog.compression_chunk_size;
|
|
numrows_pre_compression | numrows_post_compression
|
|
-------------------------+--------------------------
|
|
3 | 1
|
|
(1 row)
|
|
|
|
---------------- test1: one affected segment, one unaffected --------------
|
|
-- unaffected segment will still be recompressed in a future PR we want to avoid doing this
|
|
create table mytab_twoseg (time timestamptz not null, a int, b int, c int);
|
|
SELECT create_hypertable('mytab_twoseg', 'time', chunk_time_interval => interval '1 day');
|
|
create_hypertable
|
|
---------------------------
|
|
(3,public,mytab_twoseg,t)
|
|
(1 row)
|
|
|
|
insert into mytab_twoseg values
|
|
('2023-01-01 21:56:20.048355+02'::timestamptz, 2, NULL, 2),
|
|
('2023-01-01 21:56:20.048355+02'::timestamptz, 3, NULL, 3), --same chunk diff segment
|
|
('2023-01-01 21:57:20.048355+02'::timestamptz, 3, NULL, 3);
|
|
alter table mytab_twoseg set (timescaledb.compress, timescaledb.compress_segmentby = 'a, c');
|
|
select show_chunks as chunk_to_compress_2 from show_chunks('mytab_twoseg') limit 1 \gset
|
|
select compress_chunk(:'chunk_to_compress_2');
|
|
compress_chunk
|
|
----------------------------------------
|
|
_timescaledb_internal._hyper_3_3_chunk
|
|
(1 row)
|
|
|
|
-- should have 2 compressed rows
|
|
-- select numrows_pre_compression, numrows_post_compression from _timescaledb_catalog.compression_chunk_size ccs
|
|
-- join compressed_chunk_info_view v on ccs.chunk_id = v.chunk_id where v.compressed_chunk_schema || '.' || v.compressed_chunk_name
|
|
-- = :'chunk_to_compress_2';
|
|
select * from compression_rowcnt_view where chunk_name = :'chunk_to_compress_2';
|
|
numrows_pre_compression | numrows_post_compression | chunk_name | chunk_id
|
|
-------------------------+--------------------------+----------------------------------------+----------
|
|
3 | 2 | _timescaledb_internal._hyper_3_3_chunk | 3
|
|
(1 row)
|
|
|
|
insert into mytab_twoseg values ('2023-01-01 19:56:20.048355+02'::timestamptz, 2, NULL, 2);
|
|
select * from :chunk_to_compress_2;
|
|
time | a | b | c
|
|
-------------------------------------+---+---+---
|
|
Sun Jan 01 11:56:20.048355 2023 PST | 2 | | 2
|
|
Sun Jan 01 11:57:20.048355 2023 PST | 3 | | 3
|
|
Sun Jan 01 11:56:20.048355 2023 PST | 3 | | 3
|
|
Sun Jan 01 09:56:20.048355 2023 PST | 2 | | 2
|
|
(4 rows)
|
|
|
|
SELECT compressed_chunk_schema || '.' || compressed_chunk_name as compressed_chunk_name_2
|
|
from compressed_chunk_info_view where hypertable_name = 'mytab_twoseg' \gset
|
|
select ctid, * from :compressed_chunk_name_2;
|
|
ctid | time | a | b | c | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
-------+----------------------------------------------------------------------+---+---+---+----------------+-----------------------+-------------------------------------+-------------------------------------
|
|
(0,1) | BAAAApQ3/0H94wAClDf/Qf3jAAAAAQAAAAEAAAAAAAAADgAFKG/+g/vG | 2 | | 2 | 1 | 10 | Sun Jan 01 11:56:20.048355 2023 PST | Sun Jan 01 11:56:20.048355 2023 PST
|
|
(0,2) | BAAAApQ3/0H94//////8bHkAAAAAAgAAAAIAAAAAAAAA7gAFKHAFqwnGAAUocAzSF8U= | 3 | | 3 | 2 | 10 | Sun Jan 01 11:56:20.048355 2023 PST | Sun Jan 01 11:57:20.048355 2023 PST
|
|
(2 rows)
|
|
|
|
select _timescaledb_internal.recompress_chunk_segmentwise(:'chunk_to_compress_2');
|
|
recompress_chunk_segmentwise
|
|
----------------------------------------
|
|
_timescaledb_internal._hyper_3_3_chunk
|
|
(1 row)
|
|
|
|
-- verify that metadata count looks good
|
|
select ctid, * from :compressed_chunk_name_2;
|
|
ctid | time | a | b | c | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
-------+----------------------------------------------------------------------+---+---+---+----------------+-----------------------+-------------------------------------+-------------------------------------
|
|
(0,3) | BAAAApQ2Uhq14/////5S2LgAAAAAAgAAAAIAAAAAAAAA7gAFKG/+g/vGAAUoc1jSi8U= | 2 | | 2 | 2 | 10 | Sun Jan 01 09:56:20.048355 2023 PST | Sun Jan 01 11:56:20.048355 2023 PST
|
|
(0,4) | BAAAApQ3/0H94//////8bHkAAAAAAgAAAAIAAAAAAAAA7gAFKHAFqwnGAAUocAzSF8U= | 3 | | 3 | 2 | 10 | Sun Jan 01 11:56:20.048355 2023 PST | Sun Jan 01 11:57:20.048355 2023 PST
|
|
(2 rows)
|
|
|
|
-- verify that initial data is returned as expected
|
|
select * from :chunk_to_compress_2;
|
|
time | a | b | c
|
|
-------------------------------------+---+---+---
|
|
Sun Jan 01 11:56:20.048355 2023 PST | 2 | | 2
|
|
Sun Jan 01 09:56:20.048355 2023 PST | 2 | | 2
|
|
Sun Jan 01 11:57:20.048355 2023 PST | 3 | | 3
|
|
Sun Jan 01 11:56:20.048355 2023 PST | 3 | | 3
|
|
(4 rows)
|
|
|
|
-- should still have 2 compressed rows
|
|
select * from compression_rowcnt_view where chunk_name = :'chunk_to_compress_2';
|
|
numrows_pre_compression | numrows_post_compression | chunk_name | chunk_id
|
|
-------------------------+--------------------------+----------------------------------------+----------
|
|
4 | 2 | _timescaledb_internal._hyper_3_3_chunk | 3
|
|
(1 row)
|
|
|
|
----------------- more than one batch per segment ----------------------
|
|
-- test that metadata sequence number is correct
|
|
create table mytab2(time timestamptz not null, a int, b int, c int);
|
|
select create_hypertable('mytab2', 'time', chunk_time_interval => interval '1 week');
|
|
create_hypertable
|
|
---------------------
|
|
(5,public,mytab2,t)
|
|
(1 row)
|
|
|
|
insert into mytab2 (time, a, c) select t,s,s from
|
|
generate_series('2023-01-01 00:00:00+00'::timestamptz, '2023-01-01 00:00:00+00'::timestamptz + interval '1 day', interval '30 sec') t cross join generate_series(0,2, 1) s;
|
|
alter table mytab2 set (timescaledb.compress, timescaledb.compress_segmentby = 'a, c');
|
|
select compress_chunk(c) from show_chunks('mytab2') c;
|
|
compress_chunk
|
|
----------------------------------------
|
|
_timescaledb_internal._hyper_5_5_chunk
|
|
(1 row)
|
|
|
|
SELECT compressed_chunk_schema || '.' || compressed_chunk_name as compressed_chunk_name_2
|
|
from compressed_chunk_info_view where hypertable_name = 'mytab2'
|
|
and compressed_chunk_name is not null limit 1 \gset
|
|
insert into mytab2 values ('2023-01-01 00:00:02+00'::timestamptz, 0, NULL, 0); -- goes into the uncompressed chunk
|
|
select show_chunks('mytab2') as chunk_to_compress_2 \gset
|
|
select ctid, * from :compressed_chunk_name_2;
|
|
ctid | time | a | b | c | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
-------+----------------------------------------------------------------------------------+---+---+---+----------------+-----------------------+------------------------------+------------------------------
|
|
(0,1) | BAAAApQ0bFLXgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKHbNWYAAAAUodtDtBv8AAD5gAAAAAA== | 0 | | 0 | 1000 | 10 | Sun Jan 01 07:40:30 2023 PST | Sun Jan 01 16:00:00 2023 PST
|
|
(0,2) | BAAAApQtcC8rgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKGjVEigAAAUoaNilrv8AAD5gAAAAAA== | 0 | | 0 | 1000 | 20 | Sat Dec 31 23:20:30 2022 PST | Sun Jan 01 07:40:00 2023 PST
|
|
(0,3) | BAAAApQnSNVgAP/////+NjyAAAADcQAAAAMAAAAAAAAP7gAFKFrcytAAAAUoWuBeVv8AADbwAAAAAA== | 0 | | 0 | 881 | 30 | Sat Dec 31 16:00:00 2022 PST | Sat Dec 31 23:20:00 2022 PST
|
|
(0,4) | BAAAApQ0bFLXgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKHbNWYAAAAUodtDtBv8AAD5gAAAAAA== | 1 | | 1 | 1000 | 10 | Sun Jan 01 07:40:30 2023 PST | Sun Jan 01 16:00:00 2023 PST
|
|
(0,5) | BAAAApQtcC8rgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKGjVEigAAAUoaNilrv8AAD5gAAAAAA== | 1 | | 1 | 1000 | 20 | Sat Dec 31 23:20:30 2022 PST | Sun Jan 01 07:40:00 2023 PST
|
|
(0,6) | BAAAApQnSNVgAP/////+NjyAAAADcQAAAAMAAAAAAAAP7gAFKFrcytAAAAUoWuBeVv8AADbwAAAAAA== | 1 | | 1 | 881 | 30 | Sat Dec 31 16:00:00 2022 PST | Sat Dec 31 23:20:00 2022 PST
|
|
(0,7) | BAAAApQ0bFLXgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKHbNWYAAAAUodtDtBv8AAD5gAAAAAA== | 2 | | 2 | 1000 | 10 | Sun Jan 01 07:40:30 2023 PST | Sun Jan 01 16:00:00 2023 PST
|
|
(0,8) | BAAAApQtcC8rgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKGjVEigAAAUoaNilrv8AAD5gAAAAAA== | 2 | | 2 | 1000 | 20 | Sat Dec 31 23:20:30 2022 PST | Sun Jan 01 07:40:00 2023 PST
|
|
(0,9) | BAAAApQnSNVgAP/////+NjyAAAADcQAAAAMAAAAAAAAP7gAFKFrcytAAAAUoWuBeVv8AADbwAAAAAA== | 2 | | 2 | 881 | 30 | Sat Dec 31 16:00:00 2022 PST | Sat Dec 31 23:20:00 2022 PST
|
|
(9 rows)
|
|
|
|
-- after compression
|
|
select * from compression_rowcnt_view where chunk_name = :'chunk_to_compress_2';
|
|
numrows_pre_compression | numrows_post_compression | chunk_name | chunk_id
|
|
-------------------------+--------------------------+----------------------------------------+----------
|
|
8643 | 9 | _timescaledb_internal._hyper_5_5_chunk | 5
|
|
(1 row)
|
|
|
|
select _timescaledb_internal.recompress_chunk_segmentwise(:'chunk_to_compress_2');
|
|
recompress_chunk_segmentwise
|
|
----------------------------------------
|
|
_timescaledb_internal._hyper_5_5_chunk
|
|
(1 row)
|
|
|
|
select ctid, * from :compressed_chunk_name_2;
|
|
ctid | time | a | b | c | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
--------+------------------------------------------------------------------------------------------+---+---+---+----------------+-----------------------+------------------------------+------------------------------
|
|
(0,10) | BAAAApQ0bFLXgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKHbNWYAAAAUodtDtBv8AAD5gAAAAAA== | 0 | | 0 | 1000 | 10 | Sun Jan 01 07:40:30 2023 PST | Sun Jan 01 16:00:00 2023 PST
|
|
(0,11) | BAAAApQtcC8rgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKGjVEigAAAUoaNilrv8AAD5gAAAAAA== | 0 | | 0 | 1000 | 20 | Sat Dec 31 23:20:30 2022 PST | Sun Jan 01 07:40:00 2023 PST
|
|
(0,12) | BAAAApQnSNVgAP//////4XuAAAADcgAAAAQAAAAAAADf7gAFKFrcytAAAAUoWuBeVv8AADbgAAAAAAMZdQAAPQkA | 0 | | 0 | 882 | 30 | Sat Dec 31 16:00:00 2022 PST | Sat Dec 31 23:20:00 2022 PST
|
|
(0,13) | BAAAApQ0bFLXgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKHbNWYAAAAUodtDtBv8AAD5gAAAAAA== | 1 | | 1 | 1000 | 10 | Sun Jan 01 07:40:30 2023 PST | Sun Jan 01 16:00:00 2023 PST
|
|
(0,14) | BAAAApQtcC8rgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKGjVEigAAAUoaNilrv8AAD5gAAAAAA== | 1 | | 1 | 1000 | 20 | Sat Dec 31 23:20:30 2022 PST | Sun Jan 01 07:40:00 2023 PST
|
|
(0,15) | BAAAApQnSNVgAP/////+NjyAAAADcQAAAAMAAAAAAAAP7gAFKFrcytAAAAUoWuBeVv8AADbwAAAAAA== | 1 | | 1 | 881 | 30 | Sat Dec 31 16:00:00 2022 PST | Sat Dec 31 23:20:00 2022 PST
|
|
(0,16) | BAAAApQ0bFLXgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKHbNWYAAAAUodtDtBv8AAD5gAAAAAA== | 2 | | 2 | 1000 | 10 | Sun Jan 01 07:40:30 2023 PST | Sun Jan 01 16:00:00 2023 PST
|
|
(0,17) | BAAAApQtcC8rgP/////+NjyAAAAD6AAAAAMAAAAAAAAP7gAFKGjVEigAAAUoaNilrv8AAD5gAAAAAA== | 2 | | 2 | 1000 | 20 | Sat Dec 31 23:20:30 2022 PST | Sun Jan 01 07:40:00 2023 PST
|
|
(0,18) | BAAAApQnSNVgAP/////+NjyAAAADcQAAAAMAAAAAAAAP7gAFKFrcytAAAAUoWuBeVv8AADbwAAAAAA== | 2 | | 2 | 881 | 30 | Sat Dec 31 16:00:00 2022 PST | Sat Dec 31 23:20:00 2022 PST
|
|
(9 rows)
|
|
|
|
-- after recompression
|
|
select * from compression_rowcnt_view where chunk_name = :'chunk_to_compress_2';
|
|
numrows_pre_compression | numrows_post_compression | chunk_name | chunk_id
|
|
-------------------------+--------------------------+----------------------------------------+----------
|
|
8644 | 9 | _timescaledb_internal._hyper_5_5_chunk | 5
|
|
(1 row)
|
|
|
|
-- failing test from compression_ddl
|
|
CREATE TABLE test_defaults(time timestamptz NOT NULL, device_id int);
|
|
SELECT create_hypertable('test_defaults','time');
|
|
create_hypertable
|
|
----------------------------
|
|
(7,public,test_defaults,t)
|
|
(1 row)
|
|
|
|
ALTER TABLE test_defaults SET (timescaledb.compress,timescaledb.compress_segmentby='device_id');
|
|
-- create 2 chunks
|
|
INSERT INTO test_defaults SELECT '2000-01-01', 1;
|
|
INSERT INTO test_defaults SELECT '2001-01-01', 1;
|
|
SELECT compress_chunk(show_chunks) AS "compressed_chunk" FROM show_chunks('test_defaults') ORDER BY show_chunks::text LIMIT 1 \gset
|
|
select * from compression_rowcnt_view where chunk_name = :'compressed_chunk';
|
|
numrows_pre_compression | numrows_post_compression | chunk_name | chunk_id
|
|
-------------------------+--------------------------+----------------------------------------+----------
|
|
1 | 1 | _timescaledb_internal._hyper_7_7_chunk | 7
|
|
(1 row)
|
|
|
|
SELECT * FROM test_defaults ORDER BY 1;
|
|
time | device_id
|
|
------------------------------+-----------
|
|
Sat Jan 01 00:00:00 2000 PST | 1
|
|
Mon Jan 01 00:00:00 2001 PST | 1
|
|
(2 rows)
|
|
|
|
ALTER TABLE test_defaults ADD COLUMN c1 int;
|
|
ALTER TABLE test_defaults ADD COLUMN c2 int NOT NULL DEFAULT 42;
|
|
SELECT * FROM test_defaults ORDER BY 1,2;
|
|
time | device_id | c1 | c2
|
|
------------------------------+-----------+----+----
|
|
Sat Jan 01 00:00:00 2000 PST | 1 | | 42
|
|
Mon Jan 01 00:00:00 2001 PST | 1 | | 42
|
|
(2 rows)
|
|
|
|
INSERT INTO test_defaults SELECT '2000-01-01', 2;
|
|
SELECT * FROM test_defaults ORDER BY 1,2;
|
|
time | device_id | c1 | c2
|
|
------------------------------+-----------+----+----
|
|
Sat Jan 01 00:00:00 2000 PST | 1 | | 42
|
|
Sat Jan 01 00:00:00 2000 PST | 2 | | 42
|
|
Mon Jan 01 00:00:00 2001 PST | 1 | | 42
|
|
(3 rows)
|
|
|
|
call recompress_chunk(:'compressed_chunk');
|
|
SELECT * FROM test_defaults ORDER BY 1,2;
|
|
time | device_id | c1 | c2
|
|
------------------------------+-----------+----+----
|
|
Sat Jan 01 00:00:00 2000 PST | 1 | | 42
|
|
Sat Jan 01 00:00:00 2000 PST | 2 | | 42
|
|
Mon Jan 01 00:00:00 2001 PST | 1 | | 42
|
|
(3 rows)
|
|
|
|
-- here we will have an additional compressed row after recompression because the new
|
|
-- data corresponds to a new segment
|
|
select * from compression_rowcnt_view where chunk_name = :'compressed_chunk';
|
|
numrows_pre_compression | numrows_post_compression | chunk_name | chunk_id
|
|
-------------------------+--------------------------+----------------------------------------+----------
|
|
2 | 2 | _timescaledb_internal._hyper_7_7_chunk | 7
|
|
(1 row)
|
|
|
|
-- test prepared statements
|
|
-- PREPRE A SELECT before recompress and perform it after recompress
|
|
CREATE TABLE mytab_prep (time timestamptz, a int, b int, c int);
|
|
SELECT create_hypertable('mytab_prep', 'time');
|
|
NOTICE: adding not-null constraint to column "time"
|
|
create_hypertable
|
|
-------------------------
|
|
(9,public,mytab_prep,t)
|
|
(1 row)
|
|
|
|
INSERT INTO mytab_prep VALUES ('2023-01-01'::timestamptz, 2, NULL, 2),
|
|
('2023-01-01'::timestamptz, 2, NULL, 2);
|
|
alter table mytab_prep set (timescaledb.compress, timescaledb.compress_segmentby = 'a, c');
|
|
PREPARE p1 AS
|
|
SELECT * FROM mytab_prep;
|
|
select show_chunks as chunk_to_compress_prep from show_chunks('mytab_prep') limit 1 \gset
|
|
SELECT compress_chunk(:'chunk_to_compress_prep'); -- the output of the prepared plan would change before and after compress
|
|
compress_chunk
|
|
-----------------------------------------
|
|
_timescaledb_internal._hyper_9_10_chunk
|
|
(1 row)
|
|
|
|
INSERT INTO mytab_prep VALUES ('2023-01-01'::timestamptz, 2, 3, 2);
|
|
-- plan should be invalidated to return results from the uncompressed chunk also
|
|
EXPLAIN (COSTS OFF) EXECUTE p1;
|
|
QUERY PLAN
|
|
----------------------------------------------------------
|
|
Append
|
|
-> Custom Scan (DecompressChunk) on _hyper_9_10_chunk
|
|
-> Seq Scan on compress_hyper_10_11_chunk
|
|
-> Seq Scan on _hyper_9_10_chunk
|
|
(4 rows)
|
|
|
|
EXECUTE p1;
|
|
time | a | b | c
|
|
------------------------------+---+---+---
|
|
Sun Jan 01 00:00:00 2023 PST | 2 | | 2
|
|
Sun Jan 01 00:00:00 2023 PST | 2 | | 2
|
|
Sun Jan 01 00:00:00 2023 PST | 2 | 3 | 2
|
|
(3 rows)
|
|
|
|
-- check plan again after recompression
|
|
CALL recompress_chunk(:'chunk_to_compress_prep');
|
|
EXPLAIN (COSTS OFF) EXECUTE p1;
|
|
QUERY PLAN
|
|
----------------------------------------------------
|
|
Custom Scan (DecompressChunk) on _hyper_9_10_chunk
|
|
-> Seq Scan on compress_hyper_10_11_chunk
|
|
(2 rows)
|
|
|
|
EXECUTE p1;
|
|
time | a | b | c
|
|
------------------------------+---+---+---
|
|
Sun Jan 01 00:00:00 2023 PST | 2 | | 2
|
|
Sun Jan 01 00:00:00 2023 PST | 2 | | 2
|
|
Sun Jan 01 00:00:00 2023 PST | 2 | 3 | 2
|
|
(3 rows)
|
|
|
|
-- verify segmentwise recompression when index exists, decompress + compress otherwise
|
|
-- we verify by checking the compressed chunk after recompression in both cases.
|
|
-- in the first case, it is the same before and after
|
|
-- in the second case, a new compressed chunk is created
|
|
CREATE TABLE mytab (time timestamptz, a int, b int, c int);
|
|
SELECT create_hypertable('mytab', 'time');
|
|
NOTICE: adding not-null constraint to column "time"
|
|
create_hypertable
|
|
---------------------
|
|
(11,public,mytab,t)
|
|
(1 row)
|
|
|
|
INSERT INTO mytab VALUES ('2023-01-01'::timestamptz, 2, NULL, 2),
|
|
('2023-01-01'::timestamptz, 2, NULL, 2);
|
|
select show_chunks as chunk_to_compress_mytab from show_chunks('mytab') limit 1 \gset
|
|
-- index exists, recompression should happen segment by segment so expect a debug message
|
|
alter table mytab set (timescaledb.compress, timescaledb.compress_segmentby = 'a, c');
|
|
select compress_chunk(show_chunks('mytab'));
|
|
compress_chunk
|
|
------------------------------------------
|
|
_timescaledb_internal._hyper_11_12_chunk
|
|
(1 row)
|
|
|
|
select compressed_chunk_name as compressed_chunk_name_before_recompression from compressed_chunk_info_view where hypertable_name = 'mytab' \gset
|
|
INSERT INTO mytab VALUES ('2023-01-01'::timestamptz, 2, 3, 2);
|
|
-- segmentwise recompression should not create a new compressed chunk, so verify compressed chunk is the same after recompression
|
|
call recompress_chunk(:'chunk_to_compress_mytab');
|
|
select compressed_chunk_name as compressed_chunk_name_after_recompression from compressed_chunk_info_view where hypertable_name = 'mytab' \gset
|
|
select :'compressed_chunk_name_before_recompression' as before_segmentwise_recompression, :'compressed_chunk_name_after_recompression' as after_segmentwise_recompression;
|
|
before_segmentwise_recompression | after_segmentwise_recompression
|
|
----------------------------------+---------------------------------
|
|
compress_hyper_12_13_chunk | compress_hyper_12_13_chunk
|
|
(1 row)
|
|
|
|
SELECT decompress_chunk(show_chunks('mytab'));
|
|
decompress_chunk
|
|
------------------------------------------
|
|
_timescaledb_internal._hyper_11_12_chunk
|
|
(1 row)
|
|
|
|
alter table mytab set (timescaledb.compress = false);
|
|
alter table mytab set (timescaledb.compress);
|
|
select compress_chunk(show_chunks('mytab'));
|
|
compress_chunk
|
|
------------------------------------------
|
|
_timescaledb_internal._hyper_11_12_chunk
|
|
(1 row)
|
|
|
|
select compressed_chunk_name as compressed_chunk_name_before_recompression from compressed_chunk_info_view where hypertable_name = 'mytab' \gset
|
|
INSERT INTO mytab VALUES ('2023-01-01'::timestamptz, 2, 3, 2);
|
|
-- expect to see a different compressed chunk after recompressing now as the operation is decompress + compress
|
|
call recompress_chunk(:'chunk_to_compress_mytab');
|
|
select compressed_chunk_name as compressed_chunk_name_after_recompression from compressed_chunk_info_view where hypertable_name = 'mytab' \gset
|
|
select :'compressed_chunk_name_before_recompression' as before_recompression, :'compressed_chunk_name_after_recompression' as after_recompression;
|
|
before_recompression | after_recompression
|
|
----------------------------+----------------------------
|
|
compress_hyper_13_14_chunk | compress_hyper_13_15_chunk
|
|
(1 row)
|
|
|
|
-- check behavior with NULL values in segmentby columns
|
|
select '2022-01-01 09:00:00+00' as start_time \gset
|
|
create table nullseg_one (time timestamptz, a int, b int);
|
|
select create_hypertable('nullseg_one', 'time');
|
|
NOTICE: adding not-null constraint to column "time"
|
|
create_hypertable
|
|
---------------------------
|
|
(14,public,nullseg_one,t)
|
|
(1 row)
|
|
|
|
insert into nullseg_one values (:'start_time', 1, 1), (:'start_time', 1, 2), (:'start_time', 2,2), (:'start_time', 2,3);
|
|
alter table nullseg_one set (timescaledb.compress, timescaledb.compress_segmentby= 'a');
|
|
select compress_chunk(show_chunks('nullseg_one'));
|
|
compress_chunk
|
|
------------------------------------------
|
|
_timescaledb_internal._hyper_14_16_chunk
|
|
(1 row)
|
|
|
|
insert into nullseg_one values (:'start_time', NULL, 4);
|
|
select show_chunks as chunk_to_compress from show_chunks('nullseg_one') limit 1 \gset
|
|
select compressed_chunk_schema || '.' || compressed_chunk_name as compressed_chunk_name from compressed_chunk_info_view where hypertable_name = 'nullseg_one' \gset
|
|
call recompress_chunk(:'chunk_to_compress');
|
|
select * from :compressed_chunk_name;
|
|
time | a | b | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
----------------------------------------------------------------------+---+----------------------------------------------------------+----------------+-----------------------+------------------------------+------------------------------
|
|
BAAAAneAR/JEAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAA7gAE7wCP5IgAAATvAI/kh/8= | 1 | BAAAAAAAAAAAAgAAAAAAAAABAAAAAgAAAAEAAAAAAAAAAgAAAAAAAAAC | 2 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAA7gAE7wCP5IgAAATvAI/kh/8= | 2 | BAAAAAAAAAAAAwAAAAAAAAABAAAAAgAAAAEAAAAAAAAAAwAAAAAAAAAM | 2 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAACd4BH8kQAAAAAAQAAAAEAAAAAAAAADgAE7wCP5IgA | | BAAAAAAAAAAABAAAAAAAAAAEAAAAAQAAAAEAAAAAAAAABAAAAAAAAAAI | 1 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
(3 rows)
|
|
|
|
-- insert again, check both reindex works and NULL values properly handled
|
|
insert into nullseg_one values (:'start_time', NULL, 4);
|
|
call recompress_chunk(:'chunk_to_compress');
|
|
select * from :compressed_chunk_name;
|
|
time | a | b | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
----------------------------------------------------------------------+---+----------------------------------------------------------+----------------+-----------------------+------------------------------+------------------------------
|
|
BAAAAneAR/JEAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAA7gAE7wCP5IgAAATvAI/kh/8= | 1 | BAAAAAAAAAAAAgAAAAAAAAABAAAAAgAAAAEAAAAAAAAAAgAAAAAAAAAC | 2 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAA7gAE7wCP5IgAAATvAI/kh/8= | 2 | BAAAAAAAAAAAAwAAAAAAAAABAAAAAgAAAAEAAAAAAAAAAwAAAAAAAAAM | 2 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAA7gAE7wCP5IgAAATvAI/kh/8= | | BAAAAAAAAAAABAAAAAAAAAAAAAAAAgAAAAEAAAAAAAAABAAAAAAAAAB4 | 2 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
(3 rows)
|
|
|
|
-- test multiple NULL segmentby columns
|
|
create table nullseg_many (time timestamptz, a int, b int, c int);
|
|
select create_hypertable('nullseg_many', 'time');
|
|
NOTICE: adding not-null constraint to column "time"
|
|
create_hypertable
|
|
----------------------------
|
|
(16,public,nullseg_many,t)
|
|
(1 row)
|
|
|
|
insert into nullseg_many values (:'start_time', 1, 1, 1), (:'start_time', 1, 2, 2), (:'start_time', 2,2, 2), (:'start_time', 2,3, 3), (:'start_time', 2, NULL, 3);
|
|
alter table nullseg_many set (timescaledb.compress, timescaledb.compress_segmentby= 'a, c');
|
|
select compress_chunk(show_chunks('nullseg_many'));
|
|
compress_chunk
|
|
------------------------------------------
|
|
_timescaledb_internal._hyper_16_18_chunk
|
|
(1 row)
|
|
|
|
-- new segment (1, NULL)
|
|
insert into nullseg_many values (:'start_time', 1, 4, NULL);
|
|
select show_chunks as chunk_to_compress from show_chunks('nullseg_many') limit 1 \gset
|
|
select compressed_chunk_schema || '.' || compressed_chunk_name as compressed_chunk_name from compressed_chunk_info_view where hypertable_name = 'nullseg_many' \gset
|
|
call recompress_chunk(:'chunk_to_compress');
|
|
select * from :compressed_chunk_name;
|
|
time | a | b | c | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
----------------------------------------------------------------------+---+------------------------------------------------------------------------------------------+---+----------------+-----------------------+------------------------------+------------------------------
|
|
BAAAAneAR/JEAAACd4BH8kQAAAAAAQAAAAEAAAAAAAAADgAE7wCP5IgA | 1 | BAAAAAAAAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAAAAAAAgAAAAAAAAAC | 1 | 1 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAACd4BH8kQAAAAAAQAAAAEAAAAAAAAADgAE7wCP5IgA | 1 | BAAAAAAAAAAAAgAAAAAAAAACAAAAAQAAAAEAAAAAAAAAAwAAAAAAAAAE | 2 | 1 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAACd4BH8kQAAAAAAQAAAAEAAAAAAAAADgAE7wCP5IgA | 2 | BAAAAAAAAAAAAgAAAAAAAAACAAAAAQAAAAEAAAAAAAAAAwAAAAAAAAAE | 2 | 1 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAA7gAE7wCP5IgAAATvAI/kh/8= | 2 | BAEAAAAAAAAAAwAAAAAAAAADAAAAAQAAAAEAAAAAAAAAAwAAAAAAAAAGAAAAAgAAAAEAAAAAAAAAAQAAAAAAAAAC | 3 | 2 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAACd4BH8kQAAAAAAQAAAAEAAAAAAAAADgAE7wCP5IgA | 1 | BAAAAAAAAAAABAAAAAAAAAAEAAAAAQAAAAEAAAAAAAAABAAAAAAAAAAI | | 1 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
(5 rows)
|
|
|
|
-- insert again, check both reindex works and NULL values properly handled
|
|
-- should match existing segment (1, NULL)
|
|
insert into nullseg_many values (:'start_time', 1, NULL, NULL);
|
|
call recompress_chunk(:'chunk_to_compress');
|
|
select * from :compressed_chunk_name;
|
|
time | a | b | c | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1
|
|
----------------------------------------------------------------------+---+------------------------------------------------------------------------------------------+---+----------------+-----------------------+------------------------------+------------------------------
|
|
BAAAAneAR/JEAAACd4BH8kQAAAAAAQAAAAEAAAAAAAAADgAE7wCP5IgA | 1 | BAAAAAAAAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAAAAAAAgAAAAAAAAAC | 1 | 1 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAACd4BH8kQAAAAAAQAAAAEAAAAAAAAADgAE7wCP5IgA | 1 | BAAAAAAAAAAAAgAAAAAAAAACAAAAAQAAAAEAAAAAAAAAAwAAAAAAAAAE | 2 | 1 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAA7gAE7wCP5IgAAATvAI/kh/8= | 1 | BAEAAAAAAAAABAAAAAAAAAAEAAAAAQAAAAEAAAAAAAAABAAAAAAAAAAIAAAAAgAAAAEAAAAAAAAAAQAAAAAAAAAC | | 2 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAACd4BH8kQAAAAAAQAAAAEAAAAAAAAADgAE7wCP5IgA | 2 | BAAAAAAAAAAAAgAAAAAAAAACAAAAAQAAAAEAAAAAAAAAAwAAAAAAAAAE | 2 | 1 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
BAAAAneAR/JEAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAA7gAE7wCP5IgAAATvAI/kh/8= | 2 | BAEAAAAAAAAAAwAAAAAAAAADAAAAAQAAAAEAAAAAAAAAAwAAAAAAAAAGAAAAAgAAAAEAAAAAAAAAAQAAAAAAAAAC | 3 | 2 | 10 | Sat Jan 01 01:00:00 2022 PST | Sat Jan 01 01:00:00 2022 PST
|
|
(5 rows)
|
|
|