mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 19:13:16 +08:00
The current code would always prefer indexscan over tuplesort while doing scans of the rows from the chunk that was being compressed. The thinking was that we'd avoid doing a sort via the indexscan. The theory looked good on paper, but from various cloud customer reports we have seen that the random access of the heap pages via the indexscan was typically more expensive than doing the tuplesort. So we disable the default indexscan till we get better usecases warranting enabling it again for all scenarios. Specific use cases can enable the timescaledb.enable_compression_indexscan manually if desired.
292 lines
12 KiB
SQL
292 lines
12 KiB
SQL
-- 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.
|
|
|
|
--Enable compression path info
|
|
SET timescaledb.debug_compression_path_info= 'on';
|
|
--Table creation
|
|
CREATE TABLE tab1 (
|
|
time timestamptz not null,
|
|
id integer not null,
|
|
c1 double precision null,
|
|
c2 double precision null
|
|
);
|
|
|
|
CREATE TABLE tab2 (
|
|
time timestamptz not null,
|
|
id integer not null,
|
|
c1 double precision null,
|
|
c2 double precision null
|
|
);
|
|
--Hypertable creation
|
|
SELECT FROM create_hypertable('tab1', 'time');
|
|
SELECT FROM create_hypertable('tab2', 'time');
|
|
|
|
--Data generation
|
|
INSERT INTO tab1
|
|
SELECT
|
|
time + (INTERVAL '1 minute' * random()) AS time,
|
|
id,
|
|
random() AS c1,
|
|
random()* 100 AS c2
|
|
FROM
|
|
generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '1 hour') AS g1(time),
|
|
generate_series(1, 100, 1 ) AS g2(id)
|
|
ORDER BY
|
|
time;
|
|
|
|
--Test with indexscan enabled
|
|
SET timescaledb.enable_compression_indexscan = 'ON';
|
|
--Test Set 1.1 [ Index(ASC, Null_First), Compression(ASC, Null_First) ]
|
|
CREATE INDEX idx_asc_null_first ON tab1(id, time ASC NULLS FIRST);
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 1.1
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
--Test Set 1.2 [Index(ASC, Null_First), Compression(ASC,Null_Last)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 1.2
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
--Test Set 1.3 [Index(ASC, Null_First), Compression(DESC,Null_First)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time DESC');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 1.3
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
--DROP INDEX idx_asc_null_last
|
|
|
|
--Test Set 1.4 [Index(ASC, Null_First), Compression(DESC,Null_Last)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time DESC NULLS LAST');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 1.4
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
DROP INDEX idx_asc_null_first;
|
|
|
|
--Test Set 2.1 [Index(ASC, Null_Last), Compression(ASC,Null_First)]
|
|
CREATE INDEX idx_asc_null_last ON tab1(id, time);
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 2.1
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
--Test Set 2.2 [Index(ASC, Null_Last), Compression(ASC,Null_Last)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 2.2
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
--Test Set 2.3 [Index(ASC, Null_Last), Compression(DESC,Null_First)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time DESC');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 2.3
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
--DROP INDEX idx_asc_null_last
|
|
|
|
--Test Set 2.4 [Index(ASC, Null_Last), Compression(DESC,Null_Last)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time DESC NULLS LAST');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 2.4
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
DROP INDEX idx_asc_null_last;
|
|
|
|
--Test Set 3.1 [Index(DESC, Null_First), Compression(ASC,Null_First)]
|
|
CREATE INDEX idx_desc_null_first ON tab1(id, time DESC NULLS FIRST);
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 3.1
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
|
|
--Test Set 3.2 [Index(DESC, Null_First), Compression(ASC,Null_Last)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 3.2
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
--Test Set 3.3 [Index(DESC, Null_First), Compression(DESC,Null_First)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time DESC');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 3.3
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
--DROP INDEX idx_asc_null_last
|
|
|
|
--Test Set 3.4 [Index(DESC, Null_First), Compression(DESC,Null_Last)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time DESC NULLS LAST');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 3.4
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
DROP INDEX idx_desc_null_first;
|
|
|
|
--Test Set 4.1 [Index(DESC, Null_Last), Compression(ASC,Null_First)]
|
|
CREATE INDEX idx_desc_null_last ON tab1(id, time DESC);
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 4.1
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
--Test Set 4.2 [Index(DESC, Null_Last), Compression(ASC,Null_Last)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 4.2
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
--Test Set 4.3 [Index(DESC, Null_Last), Compression(DESC,Null_First)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time DESC');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 4.3
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
--Test Set 4.4 [Index(DESC, Null_Last), Compression(DESC,Null_Last)]
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time DESC NULLS LAST');
|
|
SELECT * FROM timescaledb_information.compression_settings;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 'time');
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
--Cleanup 4.4
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
DROP INDEX idx_desc_null_last;
|
|
|
|
--Test Set 5 GUC SET timescaledb.enable_compression_indexscan
|
|
-- Default this flag will be false.
|
|
RESET timescaledb.enable_compression_indexscan;
|
|
SHOW timescaledb.enable_compression_indexscan;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
--Test with this guc enabled
|
|
SET timescaledb.enable_compression_indexscan = 'ON';
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
|
|
--Test Set 6 Compare two compression paths
|
|
INSERT into tab2 SELECT * from tab1;
|
|
CREATE INDEX idx_asc_null_first ON tab1(id, time ASC NULLS FIRST);
|
|
CREATE INDEX idx2_asc_null_first ON tab2(id, time ASC NULLS FIRST);
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
ALTER TABLE tab2 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
RESET timescaledb.enable_compression_indexscan;
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
SET timescaledb.enable_compression_indexscan = 'ON';
|
|
SELECT compress_chunk(show_chunks('tab2'));
|
|
SELECT id, time from tab1 EXCEPT SELECT id, time from tab2;
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
SELECT decompress_chunk(show_chunks('tab2'));
|
|
DROP INDEX idx2_asc_null_first;
|
|
DROP INDEX idx_asc_null_first;
|
|
|
|
--Test Set 7.1 with Collation order_by
|
|
\set ON_ERROR_STOP 1
|
|
CREATE TABLE tab3 (
|
|
name text,
|
|
time timestamptz not null
|
|
);
|
|
|
|
SELECT FROM create_hypertable('tab3', 'time');
|
|
--Data generation
|
|
INSERT INTO tab3
|
|
SELECT
|
|
name,
|
|
time + (INTERVAL '1 minute' * random()) AS time
|
|
FROM
|
|
md5(random()::text) as name,
|
|
generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '1 hour') AS g1(time)
|
|
ORDER BY
|
|
time;
|
|
CREATE INDEX idx_asc_null_first ON tab3(name COLLATE "C", time ASC NULLS FIRST);
|
|
ALTER TABLE tab3 SET(timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 'name, time NULLS FIRST');
|
|
SELECT compress_chunk(show_chunks('tab3'));
|
|
SELECT decompress_chunk(show_chunks('tab3'));
|
|
CREATE INDEX idxcol_asc_null_first ON tab3(name, time ASC NULLS FIRST);
|
|
SELECT compress_chunk(show_chunks('tab3'));
|
|
SELECT decompress_chunk(show_chunks('tab3'));
|
|
DROP INDEX idx_asc_null_first;
|
|
DROP INDEX idxcol_asc_null_first;
|
|
|
|
--Test Set 7.1 with Collation segment_by
|
|
CREATE INDEX idx_asc_null_first ON tab3(name COLLATE "ucs_basic", time ASC NULLS FIRST);
|
|
ALTER TABLE tab3 SET(timescaledb.compress, timescaledb.compress_segmentby = 'name', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
SELECT compress_chunk(show_chunks('tab3'));
|
|
SELECT decompress_chunk(show_chunks('tab3'));
|
|
CREATE INDEX idxcol_asc_null_first ON tab3(name, time ASC NULLS FIRST);
|
|
SELECT compress_chunk(show_chunks('tab3'));
|
|
SELECT decompress_chunk(show_chunks('tab3'));
|
|
DROP INDEX idx_asc_null_first;
|
|
DROP INDEX idxcol_asc_null_first;
|
|
|
|
--Test Set 8 with multiple segment_by
|
|
CREATE INDEX idx_asc_null_first ON tab1(id, c1, time ASC NULLS FIRST);
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id, c1', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
DROP INDEX idx_asc_null_first;
|
|
CREATE INDEX idx_asc_null_first ON tab1(id, c1 DESC, time ASC NULLS FIRST);
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id, c1', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
DROP INDEX idx_asc_null_first;
|
|
|
|
--Test Set 9
|
|
--Last Column mismatch
|
|
CREATE INDEX idx_asc_null_first ON tab1(id, c1, c2);
|
|
ALTER TABLE tab1 SET(timescaledb.compress, timescaledb.compress_segmentby = 'id, c1', timescaledb.compress_orderby = 'time NULLS FIRST');
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
DROP INDEX idx_asc_null_first;
|
|
--Index Column out of order
|
|
CREATE INDEX idx_asc_null_first ON tab1(c1, id, time ASC NULLS FIRST);
|
|
SELECT compress_chunk(show_chunks('tab1'));
|
|
SELECT decompress_chunk(show_chunks('tab1'));
|
|
DROP INDEX idx_asc_null_first;
|
|
|
|
-- Can't use partial indexes for compression because they refer only to a subset of the table.
|
|
create index predicate on tab1(id, c1, time nulls first) where c2 = 0;
|
|
select count(*) from tab1;
|
|
select compress_chunk(show_chunks('tab1'));
|
|
select decompress_chunk(show_chunks('tab1'));
|
|
select count(*) from tab1;
|
|
|
|
-- Check compression progression messages
|
|
SET client_min_messages TO LOG;
|
|
select compress_chunk('_timescaledb_internal._hyper_1_1_chunk');
|
|
RESET client_min_messages;
|
|
-- Analyze and use stats now on a larger data set
|
|
INSERT INTO tab1
|
|
SELECT
|
|
time + (INTERVAL '1 minute' * random()) AS time,
|
|
id,
|
|
random() AS c1,
|
|
random()* 100 AS c2
|
|
FROM
|
|
generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '5 minutes') AS g1(time),
|
|
generate_series(1, 100, 1 ) AS g2(id)
|
|
ORDER BY
|
|
time;
|
|
ANALYZE _timescaledb_internal._hyper_1_2_chunk;
|
|
SET client_min_messages TO LOG;
|
|
select compress_chunk('_timescaledb_internal._hyper_1_2_chunk');
|
|
RESET client_min_messages;
|
|
drop index predicate;
|
|
|
|
--Tear down
|
|
DROP TABLE tab1;
|
|
DROP TABLE tab2;
|
|
DROP TABLE tab3;
|
|
SET timescaledb.debug_compression_path_info = 'off';
|