timescaledb/tsl/test/sql/transparent_decompression.sql.in
Sven Klemm 4d425d9470 Disable memoize node for append and transparent_decompression tests
With memoize enabled PG14 append tests produce a very different
plan compared to previous PG versions. To make comparing plans
between PG versions easier we disable memoize for PG14.
PG14 also modified how EXTRACT is shown in EXPLAIN output
so any query using EXTRACT will have different EXPLAIN output
between PG14 and previous versions.
2021-10-09 00:15:23 +02:00

325 lines
10 KiB
MySQL

-- 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.
\set TEST_BASE_NAME transparent_decompression
SELECT format('include/%s_load.sql', :'TEST_BASE_NAME') AS "TEST_LOAD_NAME",
format('include/%s_query.sql', :'TEST_BASE_NAME') AS "TEST_QUERY_NAME",
format('%s/results/%s_results_uncompressed.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_UNCOMPRESSED",
format('%s/results/%s_results_compressed.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_COMPRESSED" \gset
SELECT format('\! diff %s %s', :'TEST_RESULTS_UNCOMPRESSED', :'TEST_RESULTS_COMPRESSED') AS "DIFF_CMD" \gset
SET work_mem TO '50MB';
-- disable memoize node to make EXPLAIN output comparable between PG14 and previous versions
SELECT CASE WHEN current_setting('server_version_num')::int/10000 >= 14 THEN set_config('enable_memoize','off',false) ELSE 'off' END AS enable_memoize;
CREATE TABLE metrics (
filler_1 int,
filler_2 int,
filler_3 int,
time timestamptz NOT NULL,
device_id int,
device_id_peer int,
v0 int,
v1 int,
v2 float,
v3 float
);
SELECT create_hypertable ('metrics', 'time');
ALTER TABLE metrics
DROP COLUMN filler_1;
INSERT INTO metrics (time, device_id, device_id_peer, v0, v1, v2, v3)
SELECT time,
device_id,
0,
device_id + 1,
device_id + 2,
device_id + 0.5,
NULL
FROM generate_series('2000-01-01 0:00:00+0'::timestamptz, '2000-01-05 23:55:00+0', '20m') gtime (time),
generate_series(1, 5, 1) gdevice (device_id);
ALTER TABLE metrics
DROP COLUMN filler_2;
INSERT INTO metrics (time, device_id, device_id_peer, v0, v1, v2, v3)
SELECT time,
device_id,
0,
device_id - 1,
device_id + 2,
device_id + 0.5,
NULL
FROM generate_series('2000-01-06 0:00:00+0'::timestamptz, '2000-01-12 23:55:00+0', '20m') gtime (time),
generate_series(1, 5, 1) gdevice (device_id);
ALTER TABLE metrics
DROP COLUMN filler_3;
INSERT INTO metrics (time, device_id, device_id_peer, v0, v1, v2, v3)
SELECT time,
device_id,
0,
device_id,
device_id + 2,
device_id + 0.5,
NULL
FROM generate_series('2000-01-13 0:00:00+0'::timestamptz, '2000-01-19 23:55:00+0', '20m') gtime (time),
generate_series(1, 5, 1) gdevice (device_id);
ANALYZE metrics;
-- create identical hypertable with space partitioning
CREATE TABLE metrics_space (
filler_1 int,
filler_2 int,
filler_3 int,
time timestamptz NOT NULL,
device_id int,
device_id_peer int,
v0 int,
v1 float,
v2 float,
v3 float
);
SELECT create_hypertable ('metrics_space', 'time', 'device_id', 3);
ALTER TABLE metrics_space
DROP COLUMN filler_1;
INSERT INTO metrics_space (time, device_id, device_id_peer, v0, v1, v2, v3)
SELECT time,
device_id,
0,
device_id + 1,
device_id + 2,
device_id + 0.5,
NULL
FROM generate_series('2000-01-01 0:00:00+0'::timestamptz, '2000-01-05 23:55:00+0', '20m') gtime (time),
generate_series(1, 5, 1) gdevice (device_id);
ALTER TABLE metrics_space
DROP COLUMN filler_2;
INSERT INTO metrics_space (time, device_id, device_id_peer, v0, v1, v2, v3)
SELECT time,
device_id,
0,
device_id + 1,
device_id + 2,
device_id + 0.5,
NULL
FROM generate_series('2000-01-06 0:00:00+0'::timestamptz, '2000-01-12 23:55:00+0', '20m') gtime (time),
generate_series(1, 5, 1) gdevice (device_id);
ALTER TABLE metrics_space
DROP COLUMN filler_3;
INSERT INTO metrics_space (time, device_id, device_id_peer, v0, v1, v2, v3)
SELECT time,
device_id,
0,
device_id + 1,
device_id + 2,
device_id + 0.5,
NULL
FROM generate_series('2000-01-13 0:00:00+0'::timestamptz, '2000-01-19 23:55:00+0', '20m') gtime (time),
generate_series(1, 5, 1) gdevice (device_id);
ANALYZE metrics_space;
-- run queries on uncompressed hypertable and store result
\set PREFIX ''
\set PREFIX_VERBOSE ''
\set PREFIX_NO_ANALYZE ''
\set ECHO none
SET client_min_messages TO error;
\o :TEST_RESULTS_UNCOMPRESSED
\set TEST_TABLE 'metrics'
\ir :TEST_QUERY_NAME
\set TEST_TABLE 'metrics_space'
\ir :TEST_QUERY_NAME
\o
RESET client_min_messages;
\set ECHO all
-- compress first and last chunk on the hypertable
ALTER TABLE metrics SET (timescaledb.compress, timescaledb.compress_orderby = 'v0, v1 desc, time', timescaledb.compress_segmentby = 'device_id,device_id_peer');
SELECT compress_chunk ('_timescaledb_internal._hyper_1_1_chunk');
SELECT compress_chunk ('_timescaledb_internal._hyper_1_3_chunk');
-- compress some chunks on space partitioned hypertable
-- we compress all chunks of first time slice, none of second, and 2 of the last time slice
ALTER TABLE metrics_space SET (timescaledb.compress, timescaledb.compress_orderby = 'v0, v1 desc, time', timescaledb.compress_segmentby = 'device_id,device_id_peer');
SELECT compress_chunk ('_timescaledb_internal._hyper_2_4_chunk');
SELECT compress_chunk ('_timescaledb_internal._hyper_2_5_chunk');
SELECT compress_chunk ('_timescaledb_internal._hyper_2_6_chunk');
SELECT compress_chunk ('_timescaledb_internal._hyper_2_10_chunk');
SELECT compress_chunk ('_timescaledb_internal._hyper_2_11_chunk');
SELECT ht.schema_name || '.' || ht.table_name AS "METRICS_COMPRESSED"
FROM _timescaledb_catalog.hypertable ht
INNER JOIN _timescaledb_catalog.hypertable ht2 ON ht.id = ht2.compressed_hypertable_id
AND ht2.table_name = 'metrics' \gset
SELECT ht.schema_name || '.' || ht.table_name AS "METRICS_SPACE_COMPRESSED"
FROM _timescaledb_catalog.hypertable ht
INNER JOIN _timescaledb_catalog.hypertable ht2 ON ht.id = ht2.compressed_hypertable_id
AND ht2.table_name = 'metrics_space' \gset
\c :TEST_DBNAME :ROLE_SUPERUSER
-- Index created using query saved in variable used because there was
-- no standard way to create an index on a compressed table.
-- Once a standard way exists, modify this test to use that method.
CREATE INDEX c_index ON :METRICS_COMPRESSED (device_id);
CREATE INDEX c_space_index ON :METRICS_SPACE_COMPRESSED (device_id);
CREATE INDEX c_index_2 ON :METRICS_COMPRESSED (device_id, _ts_meta_count);
CREATE INDEX c_space_index_2 ON :METRICS_SPACE_COMPRESSED (device_id, _ts_meta_count);
CREATE INDEX ON :METRICS_COMPRESSED (device_id_peer);
CREATE INDEX ON :METRICS_SPACE_COMPRESSED (device_id_peer);
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
CREATE INDEX ON metrics_space (device_id, device_id_peer, v0, v1 DESC, time);
CREATE INDEX ON metrics_space (device_id, device_id_peer DESC, v0, v1 DESC, time);
CREATE INDEX ON metrics_space (device_id DESC, device_id_peer DESC, v0, v1 DESC, time);
ANALYZE metrics_space;
-- run queries on compressed hypertable and store result
\set PREFIX ''
\set PREFIX_VERBOSE ''
\set PREFIX_NO_ANALYZE ''
\set ECHO none
SET client_min_messages TO error;
\o :TEST_RESULTS_COMPRESSED
\set TEST_TABLE 'metrics'
\ir :TEST_QUERY_NAME
\set TEST_TABLE 'metrics_space'
\ir :TEST_QUERY_NAME
\o
RESET client_min_messages;
\set ECHO all
\set PREFIX 'EXPLAIN (analyze, costs off, timing off, summary off)'
\set PREFIX_VERBOSE 'EXPLAIN (analyze, costs off, timing off, summary off, verbose)'
\set PREFIX_NO_ANALYZE 'EXPLAIN (verbose, costs off)'
-- we disable parallelism here otherwise EXPLAIN ANALYZE output
-- will be not stable and differ depending on worker assignment
SET max_parallel_workers_per_gather TO 0;
-- get explain for queries on hypertable with compression
\set TEST_TABLE 'metrics'
\ir :TEST_QUERY_NAME
\set TEST_TABLE 'metrics_space'
\ir :TEST_QUERY_NAME
\ir include/transparent_decompression_ordered.sql
\ir include/transparent_decompression_systemcolumns.sql
\ir include/transparent_decompression_undiffed.sql
-- diff compressed and uncompressed results
:DIFF_CMD
-- check hypertable detection in views
CREATE VIEW ht_view AS
SELECT *,
0 AS res
FROM metrics
UNION ALL
SELECT *,
1 AS res
FROM metrics;
CREATE FUNCTION ht_func() RETURNS SETOF metrics LANGUAGE SQL STABLE AS
$sql$
SELECT time,
device_id,
device_id_peer,
v0, v1, v2, v3
FROM ht_view
WHERE res = 0;
$sql$;
-- should have decompresschunk node
:PREFIX SELECT * FROM ht_func();
\c
-- plan should be identical to previous plan in fresh session
:PREFIX SELECT * FROM ht_func();
-- repro for core dump related to total_table_pages setting that get
-- adjusted during decompress path.
CREATE SEQUENCE vessel_id_seq
INCREMENT 1
START 1 MINVALUE 1
MAXVALUE 9223372036854775807
CACHE 1;
CREATE TABLE motion_table(
id bigint NOT NULL DEFAULT nextval('vessel_id_seq'::regclass) ,
datalogger_id bigint ,
vessel_id bigint ,
bus_id smallint ,
src_id smallint ,
dataloggertime timestamp with time zone ,
interval_s real );
CREATE INDEX
motion_table_t2_datalogger_id_idx on motion_table (datalogger_id);
CREATE INDEX motion_table_t2_dataloggertime_idx on motion_table(dataloggertime DESC);
CREATE INDEX motion_table_t2_vessel_id_idx on motion_table(vessel_id);
SELECT create_hypertable( 'motion_table', 'dataloggertime', chunk_time_interval=> '7 days'::interval);
--- do not modify the data. We need atleast this volume to reproduce issues with pages/tuple counts etc. ---
INSERT into motion_table(datalogger_id, vessel_id, bus_id, src_id,
dataloggertime, interval_s)
SELECT 1, random(), random() , random() ,
generate_series( '2020-01-02 10:00'::timestamp, '2020-01-10 10::00'::timestamp, '1 min'::interval), 1.1;
INSERT into motion_table(datalogger_id, vessel_id, bus_id, src_id,
dataloggertime, interval_s)
SELECT 1, random(), 2, 3,
generate_series( '2020-01-10 8:00'::timestamp, '2020-01-10 10::00'::timestamp, '1 min'::interval), 1.1;
ALTER TABLE motion_table SET ( timescaledb.compress,
timescaledb.compress_segmentby = 'vessel_id, datalogger_id, bus_id, src_id' , timescaledb.compress_orderby = 'dataloggertime' );
--have 2 chunks --
SELECT COUNT(*)
FROM timescaledb_information.chunks
WHERE hypertable_name = 'motion_table';
-- compress only the first one ---
SELECT compress_chunk( chunk_table)
FROM ( SELECT chunk_schema || '.' || chunk_name as chunk_table
FROM timescaledb_information.chunks
WHERE hypertable_name = 'motion_table' ORDER BY range_start limit 1 ) q;
--call to decompress chunk on 1 of the chunks
SELECT count(*) from motion_table;
--END of test for page settings