Skip to content

Commit

Permalink
Avoid decompressing batches using an empty slot
Browse files Browse the repository at this point in the history
When running COPY command into a compressed hypertable, we
could end up using an empty slot for filtering compressed batches.
This happens when a previously created copy buffer for a chunk
does not contain any new tuples for inserting. The fix is to
verify slots before attempting to do anything else.
  • Loading branch information
antekresic committed Sep 27, 2023
1 parent 32a695e commit 1932c02
Show file tree
Hide file tree
Showing 5 changed files with 1,070 additions and 0 deletions.
1 change: 1 addition & 0 deletions .unreleased/PR_6117
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes: #6117 Avoid decompressing batches using an empty slot
9 changes: 9 additions & 0 deletions tsl/src/compression/compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -2000,6 +2000,15 @@ create_segment_filter_scankey(RowDecompressor *decompressor, char *segment_filte
void
decompress_batches_for_insert(ChunkInsertState *cis, Chunk *chunk, TupleTableSlot *slot)
{
/* COPY operation can end up flushing an empty buffer which
* could in turn send an empty slot our way. No need to decompress
* anything if that happens.
*/
if (TTS_EMPTY(slot))
{
return;
}

Relation out_rel = cis->rel;

if (!ts_indexing_relation_has_primary_or_unique_index(out_rel))
Expand Down
29 changes: 29 additions & 0 deletions tsl/test/expected/compression_insert.out
Original file line number Diff line number Diff line change
Expand Up @@ -1013,3 +1013,32 @@ select count(compress_chunk(ch)) FROM show_chunks('test4') ch;
ALTER TABLE test4 DROP COLUMN two;
INSERT INTO test4 VALUES ('2021-10-14 17:50:16.207', '7', NULL);
INSERT INTO test4 (timestamp, ident) VALUES ('2021-10-14 17:50:16.207', '7');
DROP TABLE test4;
-- Test COPY when trying to flush an empty buffer
-- In this case we send an empty slot used to
-- search for compressed tuples.
CREATE TABLE test_copy (
timestamp int not null,
id bigint
);
CREATE UNIQUE INDEX timestamp_id_idx ON test_copy(timestamp, id);
SELECT * FROM create_hypertable('test_copy', 'timestamp', chunk_time_interval=>10);
hypertable_id | schema_name | table_name | created
---------------+-------------+------------+---------
22 | public | test_copy | t
(1 row)

ALTER TABLE test_copy SET (
timescaledb.compress,
timescaledb.compress_orderby = 'timestamp',
timescaledb.compress_segmentby = 'id'
);
INSERT INTO test_copy SELECT generate_series(1,25,1), -1;
SELECT count(compress_chunk(ch)) FROM show_chunks('test_copy') ch;
count
-------
3
(1 row)

\copy test_copy FROM data/copy_data.csv WITH CSV HEADER;
DROP TABLE test_copy;
29 changes: 29 additions & 0 deletions tsl/test/sql/compression_insert.sql
Original file line number Diff line number Diff line change
Expand Up @@ -659,3 +659,32 @@ ALTER TABLE test4 DROP COLUMN two;
INSERT INTO test4 VALUES ('2021-10-14 17:50:16.207', '7', NULL);
INSERT INTO test4 (timestamp, ident) VALUES ('2021-10-14 17:50:16.207', '7');

DROP TABLE test4;


-- Test COPY when trying to flush an empty buffer
-- In this case we send an empty slot used to
-- search for compressed tuples.

CREATE TABLE test_copy (
timestamp int not null,
id bigint
);

CREATE UNIQUE INDEX timestamp_id_idx ON test_copy(timestamp, id);

SELECT * FROM create_hypertable('test_copy', 'timestamp', chunk_time_interval=>10);

ALTER TABLE test_copy SET (
timescaledb.compress,
timescaledb.compress_orderby = 'timestamp',
timescaledb.compress_segmentby = 'id'
);

INSERT INTO test_copy SELECT generate_series(1,25,1), -1;

SELECT count(compress_chunk(ch)) FROM show_chunks('test_copy') ch;

\copy test_copy FROM data/copy_data.csv WITH CSV HEADER;

DROP TABLE test_copy;
Loading

0 comments on commit 1932c02

Please sign in to comment.