timescaledb/tsl/test/sql/compression_indexscan.sql
Nikhil Sontakke 4f912f77ca Disable default indexscan for compression
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.
2024-02-12 22:09:21 +05:30

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';