From e2da5606cf649a47bf933cb2e107661ce10d8e64 Mon Sep 17 00:00:00 2001 From: Dmitry Simonenko Date: Wed, 1 Apr 2020 14:15:44 +0300 Subject: [PATCH] Add test for jit compilation support This test also covers a failure case descibed in the issue #1262. --- tsl/test/expected/jit-11.out | 236 +++++++++++++++++++++++++++ tsl/test/expected/jit-12.out | 236 +++++++++++++++++++++++++++ tsl/test/sql/.gitignore | 1 + tsl/test/sql/CMakeLists.txt | 11 +- tsl/test/sql/include/jit_cleanup.sql | 7 + tsl/test/sql/include/jit_load.sql | 37 +++++ tsl/test/sql/include/jit_query.sql | 41 +++++ tsl/test/sql/jit.sql.in | 59 +++++++ 8 files changed, 627 insertions(+), 1 deletion(-) create mode 100644 tsl/test/expected/jit-11.out create mode 100644 tsl/test/expected/jit-12.out create mode 100644 tsl/test/sql/include/jit_cleanup.sql create mode 100644 tsl/test/sql/include/jit_load.sql create mode 100644 tsl/test/sql/include/jit_query.sql create mode 100644 tsl/test/sql/jit.sql.in diff --git a/tsl/test/expected/jit-11.out b/tsl/test/expected/jit-11.out new file mode 100644 index 000000000..efb1aefb5 --- /dev/null +++ b/tsl/test/expected/jit-11.out @@ -0,0 +1,236 @@ +-- 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 jit +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('include/%s_cleanup.sql', :'TEST_BASE_NAME') as "TEST_CLEANUP_NAME", + format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_OPTIMIZED", + format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_UNOPTIMIZED" +\gset +SELECT format('\! diff -u --label "Unoptimized results" --label "Optimized results" %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_OPTIMIZED') as "DIFF_CMD" +\gset +-- enable all jit optimizations +-- +-- disable jit_tuple_deforming for PG11 as a temporary solution +-- until it fixed +-- +SET jit=on; +SET jit_above_cost=0; +SET jit_inline_above_cost=0; +SET jit_optimize_above_cost=0; +SELECT + CASE WHEN current_setting('server_version_num')::int < 120000 + THEN 0 ELSE 1 + END AS "USE_JIT_DEFORMING" +\gset +SET jit_tuple_deforming=:USE_JIT_DEFORMING; +\ir :TEST_LOAD_NAME +-- 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. +CREATE TABLE jit_test(time timestamp NOT NULL, temp float); +SELECT create_hypertable('jit_test', 'time'); + create_hypertable +----------------------- + (1,public,jit_test,t) +(1 row) + +CREATE TABLE jit_test_interval(id int NOT NULL, temp float); +SELECT create_hypertable('jit_test_interval', 'id', chunk_time_interval => 10); + create_hypertable +-------------------------------- + (2,public,jit_test_interval,t) +(1 row) + +CREATE TABLE jit_test_contagg ( + observation_time TIMESTAMPTZ NOT NULL, + device_id TEXT NOT NULL, + metric DOUBLE PRECISION NOT NULL, + PRIMARY KEY(observation_time, device_id) +); +SELECT table_name FROM create_hypertable('jit_test_contagg', 'observation_time'); + table_name +------------------ + jit_test_contagg +(1 row) + +CREATE VIEW jit_device_summary +WITH (timescaledb.continuous) +AS +SELECT + time_bucket('1 hour', observation_time) as bucket, + device_id, + avg(metric) as metric_avg, + max(metric)-min(metric) as metric_spread +FROM + jit_test_contagg +GROUP BY bucket, device_id; +psql:include/jit_load.sql:28: NOTICE: adding index _materialized_hypertable_4_device_id_bucket_idx ON _timescaledb_internal._materialized_hypertable_4 USING BTREE(device_id, bucket) +INSERT INTO jit_test_contagg +SELECT ts, 'device_1', (EXTRACT(EPOCH FROM ts)) from generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '30 minutes') ts; +INSERT INTO jit_test_contagg +SELECT ts, 'device_2', (EXTRACT(EPOCH FROM ts)) from generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '30 minutes') ts; +ALTER VIEW jit_device_summary SET (timescaledb.max_interval_per_job = '60 day'); +SET timescaledb.current_timestamp_mock = '2018-12-31 00:00'; +REFRESH MATERIALIZED VIEW jit_device_summary; +\set PREFIX 'EXPLAIN (VERBOSE, TIMING OFF, COSTS OFF, SUMMARY OFF)' +\ir :TEST_QUERY_NAME +-- 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. +-- github issue #1262 +-- +:PREFIX +INSERT INTO jit_test VALUES('2017-01-20T09:00:01', 22.5) RETURNING *; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + Output: "time", temp + -> Insert on public.jit_test + Output: "time", temp + -> Custom Scan (ChunkDispatch) + Output: 'Fri Jan 20 09:00:01 2017'::timestamp without time zone, '22.5'::double precision + -> Result + Output: 'Fri Jan 20 09:00:01 2017'::timestamp without time zone, '22.5'::double precision +(8 rows) + +:PREFIX +INSERT INTO jit_test VALUES ('2017-01-20T09:00:02', 2), + ('2017-01-20T09:00:03', 5), + ('2017-01-20T09:00:04', 10); + QUERY PLAN +-------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on public.jit_test + -> Custom Scan (ChunkDispatch) + Output: "*VALUES*".column1, "*VALUES*".column2 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1, "*VALUES*".column2 +(6 rows) + +:PREFIX +SELECT * FROM jit_test WHERE temp > 5 and temp <= 10 ORDER BY time; + QUERY PLAN +-------------------------------- + Sort + Output: "time", temp + Sort Key: jit_test."time" + -> Result + Output: "time", temp + One-Time Filter: false +(6 rows) + +-- update with iteration over chunks +-- +:PREFIX +INSERT INTO jit_test_interval (SELECT x, x / 2.3 FROM generate_series(0, 100) x) RETURNING *; + QUERY PLAN +------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + Output: jit_test_interval.id, jit_test_interval.temp + -> Insert on public.jit_test_interval + Output: jit_test_interval.id, jit_test_interval.temp + -> Custom Scan (ChunkDispatch) + Output: x.x, ((((x.x)::numeric / 2.3))::double precision) + -> Function Scan on pg_catalog.generate_series x + Output: x.x, ((x.x)::numeric / 2.3) + Function Call: generate_series(0, 100) +(9 rows) + +:PREFIX +SELECT * FROM jit_test_interval WHERE id >= 23 and id < 73 ORDER BY id; + QUERY PLAN +---------------------------------- + Sort + Output: id, temp + Sort Key: jit_test_interval.id + -> Result + Output: id, temp + One-Time Filter: false +(6 rows) + +:PREFIX +UPDATE jit_test_interval SET temp = temp * 2.3 WHERE id >= 23 and id < 73; + QUERY PLAN +------------------------------------------------------------------------------------ + Update on public.jit_test_interval + -> Index Scan using jit_test_interval_id_idx on public.jit_test_interval + Output: id, (temp * '2.3'::double precision), ctid + Index Cond: ((jit_test_interval.id >= 23) AND (jit_test_interval.id < 73)) +(4 rows) + +:PREFIX +SELECT * FROM jit_test_interval ORDER BY id; + QUERY PLAN +---------------------------------- + Sort + Output: id, temp + Sort Key: jit_test_interval.id + -> Result + Output: id, temp + One-Time Filter: false +(6 rows) + +:PREFIX +SELECT time_bucket(10, id), avg(temp) +FROM jit_test_interval +GROUP BY 1 +ORDER BY 1; + QUERY PLAN +----------------------------------------------------------- + GroupAggregate + Output: (time_bucket(10, id)), avg(temp) + Group Key: (time_bucket(10, jit_test_interval.id)) + -> Sort + Output: (time_bucket(10, id)), temp + Sort Key: (time_bucket(10, jit_test_interval.id)) + -> Result + Output: time_bucket(10, id), temp + One-Time Filter: false +(9 rows) + +-- test continuous aggregates usage with forced jit (based on continuous_aggs_usage.sql) +-- +:PREFIX +SELECT * FROM jit_device_summary WHERE metric_spread = 1800 ORDER BY bucket DESC, device_id LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, (_timescaledb_internal.finalize_agg('avg(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_3_3, NULL::double precision)), ((_timescaledb_internal.finalize_agg('max(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_4, NULL::double precision) - _timescaledb_internal.finalize_agg('min(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_5, NULL::double precision))) + -> Sort + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, (_timescaledb_internal.finalize_agg('avg(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_3_3, NULL::double precision)), ((_timescaledb_internal.finalize_agg('max(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_4, NULL::double precision) - _timescaledb_internal.finalize_agg('min(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_5, NULL::double precision))) + Sort Key: _materialized_hypertable_4.bucket DESC, _materialized_hypertable_4.device_id + -> Append + -> GroupAggregate + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, _timescaledb_internal.finalize_agg('avg(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_3_3, NULL::double precision), (_timescaledb_internal.finalize_agg('max(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_4, NULL::double precision) - _timescaledb_internal.finalize_agg('min(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_5, NULL::double precision)) + Group Key: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id + Filter: ((_timescaledb_internal.finalize_agg('max(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_4, NULL::double precision) - _timescaledb_internal.finalize_agg('min(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_5, NULL::double precision)) = '1800'::double precision) + -> Sort + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, _materialized_hypertable_4.agg_3_3, _materialized_hypertable_4.agg_4_4, _materialized_hypertable_4.agg_4_5 + Sort Key: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id + -> Custom Scan (ChunkAppend) on _timescaledb_internal._materialized_hypertable_4 + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, _materialized_hypertable_4.agg_3_3, _materialized_hypertable_4.agg_4_4, _materialized_hypertable_4.agg_4_5 + Startup Exclusion: true + Runtime Exclusion: false + Chunks excluded during startup: 0 + -> Index Scan using _hyper_4_6_chunk__materialized_hypertable_4_bucket_idx on _timescaledb_internal._hyper_4_6_chunk + Output: _hyper_4_6_chunk.bucket, _hyper_4_6_chunk.device_id, _hyper_4_6_chunk.agg_3_3, _hyper_4_6_chunk.agg_4_4, _hyper_4_6_chunk.agg_4_5 + Index Cond: (_hyper_4_6_chunk.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(3)), '-infinity'::timestamp with time zone)) + -> HashAggregate + Output: (time_bucket('@ 1 hour'::interval, jit_test_contagg.observation_time)), jit_test_contagg.device_id, avg(jit_test_contagg.metric), (max(jit_test_contagg.metric) - min(jit_test_contagg.metric)) + Group Key: time_bucket('@ 1 hour'::interval, jit_test_contagg.observation_time), jit_test_contagg.device_id + Filter: ((max(jit_test_contagg.metric) - min(jit_test_contagg.metric)) = '1800'::double precision) + -> Custom Scan (ChunkAppend) on public.jit_test_contagg + Output: time_bucket('@ 1 hour'::interval, jit_test_contagg.observation_time), jit_test_contagg.device_id, jit_test_contagg.metric + Startup Exclusion: true + Runtime Exclusion: false + Chunks excluded during startup: 4 + -> Index Scan using _hyper_3_5_chunk_jit_test_contagg_observation_time_idx on _timescaledb_internal._hyper_3_5_chunk + Output: _hyper_3_5_chunk.observation_time, _hyper_3_5_chunk.device_id, _hyper_3_5_chunk.metric + Index Cond: (_hyper_3_5_chunk.observation_time >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(3)), '-infinity'::timestamp with time zone)) +(33 rows) + +-- generate the results into two different files +\set ECHO errors +--TEST END-- diff --git a/tsl/test/expected/jit-12.out b/tsl/test/expected/jit-12.out new file mode 100644 index 000000000..00e960eff --- /dev/null +++ b/tsl/test/expected/jit-12.out @@ -0,0 +1,236 @@ +-- 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 jit +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('include/%s_cleanup.sql', :'TEST_BASE_NAME') as "TEST_CLEANUP_NAME", + format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_OPTIMIZED", + format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_UNOPTIMIZED" +\gset +SELECT format('\! diff -u --label "Unoptimized results" --label "Optimized results" %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_OPTIMIZED') as "DIFF_CMD" +\gset +-- enable all jit optimizations +-- +-- disable jit_tuple_deforming for PG11 as a temporary solution +-- until it fixed +-- +SET jit=on; +SET jit_above_cost=0; +SET jit_inline_above_cost=0; +SET jit_optimize_above_cost=0; +SELECT + CASE WHEN current_setting('server_version_num')::int < 120000 + THEN 0 ELSE 1 + END AS "USE_JIT_DEFORMING" +\gset +SET jit_tuple_deforming=:USE_JIT_DEFORMING; +\ir :TEST_LOAD_NAME +-- 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. +CREATE TABLE jit_test(time timestamp NOT NULL, temp float); +SELECT create_hypertable('jit_test', 'time'); + create_hypertable +----------------------- + (1,public,jit_test,t) +(1 row) + +CREATE TABLE jit_test_interval(id int NOT NULL, temp float); +SELECT create_hypertable('jit_test_interval', 'id', chunk_time_interval => 10); + create_hypertable +-------------------------------- + (2,public,jit_test_interval,t) +(1 row) + +CREATE TABLE jit_test_contagg ( + observation_time TIMESTAMPTZ NOT NULL, + device_id TEXT NOT NULL, + metric DOUBLE PRECISION NOT NULL, + PRIMARY KEY(observation_time, device_id) +); +SELECT table_name FROM create_hypertable('jit_test_contagg', 'observation_time'); + table_name +------------------ + jit_test_contagg +(1 row) + +CREATE VIEW jit_device_summary +WITH (timescaledb.continuous) +AS +SELECT + time_bucket('1 hour', observation_time) as bucket, + device_id, + avg(metric) as metric_avg, + max(metric)-min(metric) as metric_spread +FROM + jit_test_contagg +GROUP BY bucket, device_id; +psql:include/jit_load.sql:28: NOTICE: adding index _materialized_hypertable_4_device_id_bucket_idx ON _timescaledb_internal._materialized_hypertable_4 USING BTREE(device_id, bucket) +INSERT INTO jit_test_contagg +SELECT ts, 'device_1', (EXTRACT(EPOCH FROM ts)) from generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '30 minutes') ts; +INSERT INTO jit_test_contagg +SELECT ts, 'device_2', (EXTRACT(EPOCH FROM ts)) from generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '30 minutes') ts; +ALTER VIEW jit_device_summary SET (timescaledb.max_interval_per_job = '60 day'); +SET timescaledb.current_timestamp_mock = '2018-12-31 00:00'; +REFRESH MATERIALIZED VIEW jit_device_summary; +\set PREFIX 'EXPLAIN (VERBOSE, TIMING OFF, COSTS OFF, SUMMARY OFF)' +\ir :TEST_QUERY_NAME +-- 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. +-- github issue #1262 +-- +:PREFIX +INSERT INTO jit_test VALUES('2017-01-20T09:00:01', 22.5) RETURNING *; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + Output: jit_test."time", jit_test.temp + -> Insert on public.jit_test + Output: jit_test."time", jit_test.temp + -> Custom Scan (ChunkDispatch) + Output: 'Fri Jan 20 09:00:01 2017'::timestamp without time zone, '22.5'::double precision + -> Result + Output: 'Fri Jan 20 09:00:01 2017'::timestamp without time zone, '22.5'::double precision +(8 rows) + +:PREFIX +INSERT INTO jit_test VALUES ('2017-01-20T09:00:02', 2), + ('2017-01-20T09:00:03', 5), + ('2017-01-20T09:00:04', 10); + QUERY PLAN +-------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on public.jit_test + -> Custom Scan (ChunkDispatch) + Output: "*VALUES*".column1, "*VALUES*".column2 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1, "*VALUES*".column2 +(6 rows) + +:PREFIX +SELECT * FROM jit_test WHERE temp > 5 and temp <= 10 ORDER BY time; + QUERY PLAN +-------------------------------- + Sort + Output: "time", temp + Sort Key: jit_test."time" + -> Result + Output: "time", temp + One-Time Filter: false +(6 rows) + +-- update with iteration over chunks +-- +:PREFIX +INSERT INTO jit_test_interval (SELECT x, x / 2.3 FROM generate_series(0, 100) x) RETURNING *; + QUERY PLAN +------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + Output: jit_test_interval.id, jit_test_interval.temp + -> Insert on public.jit_test_interval + Output: jit_test_interval.id, jit_test_interval.temp + -> Custom Scan (ChunkDispatch) + Output: x.x, ((((x.x)::numeric / 2.3))::double precision) + -> Function Scan on pg_catalog.generate_series x + Output: x.x, ((x.x)::numeric / 2.3) + Function Call: generate_series(0, 100) +(9 rows) + +:PREFIX +SELECT * FROM jit_test_interval WHERE id >= 23 and id < 73 ORDER BY id; + QUERY PLAN +---------------------------------- + Sort + Output: id, temp + Sort Key: jit_test_interval.id + -> Result + Output: id, temp + One-Time Filter: false +(6 rows) + +:PREFIX +UPDATE jit_test_interval SET temp = temp * 2.3 WHERE id >= 23 and id < 73; + QUERY PLAN +------------------------------------------------------------------------------------ + Update on public.jit_test_interval + -> Index Scan using jit_test_interval_id_idx on public.jit_test_interval + Output: id, (temp * '2.3'::double precision), ctid + Index Cond: ((jit_test_interval.id >= 23) AND (jit_test_interval.id < 73)) +(4 rows) + +:PREFIX +SELECT * FROM jit_test_interval ORDER BY id; + QUERY PLAN +---------------------------------- + Sort + Output: id, temp + Sort Key: jit_test_interval.id + -> Result + Output: id, temp + One-Time Filter: false +(6 rows) + +:PREFIX +SELECT time_bucket(10, id), avg(temp) +FROM jit_test_interval +GROUP BY 1 +ORDER BY 1; + QUERY PLAN +----------------------------------------------------------- + GroupAggregate + Output: (time_bucket(10, id)), avg(temp) + Group Key: (time_bucket(10, jit_test_interval.id)) + -> Sort + Output: (time_bucket(10, id)), temp + Sort Key: (time_bucket(10, jit_test_interval.id)) + -> Result + Output: time_bucket(10, id), temp + One-Time Filter: false +(9 rows) + +-- test continuous aggregates usage with forced jit (based on continuous_aggs_usage.sql) +-- +:PREFIX +SELECT * FROM jit_device_summary WHERE metric_spread = 1800 ORDER BY bucket DESC, device_id LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, (_timescaledb_internal.finalize_agg('avg(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_3_3, NULL::double precision)), ((_timescaledb_internal.finalize_agg('max(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_4, NULL::double precision) - _timescaledb_internal.finalize_agg('min(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_5, NULL::double precision))) + -> Sort + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, (_timescaledb_internal.finalize_agg('avg(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_3_3, NULL::double precision)), ((_timescaledb_internal.finalize_agg('max(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_4, NULL::double precision) - _timescaledb_internal.finalize_agg('min(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_5, NULL::double precision))) + Sort Key: _materialized_hypertable_4.bucket DESC, _materialized_hypertable_4.device_id + -> Append + -> GroupAggregate + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, _timescaledb_internal.finalize_agg('avg(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_3_3, NULL::double precision), (_timescaledb_internal.finalize_agg('max(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_4, NULL::double precision) - _timescaledb_internal.finalize_agg('min(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_5, NULL::double precision)) + Group Key: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id + Filter: ((_timescaledb_internal.finalize_agg('max(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_4, NULL::double precision) - _timescaledb_internal.finalize_agg('min(double precision)'::text, NULL::name, NULL::name, '{{pg_catalog,float8}}'::name[], _materialized_hypertable_4.agg_4_5, NULL::double precision)) = '1800'::double precision) + -> Sort + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, _materialized_hypertable_4.agg_3_3, _materialized_hypertable_4.agg_4_4, _materialized_hypertable_4.agg_4_5 + Sort Key: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id + -> Custom Scan (ChunkAppend) on _timescaledb_internal._materialized_hypertable_4 + Output: _materialized_hypertable_4.bucket, _materialized_hypertable_4.device_id, _materialized_hypertable_4.agg_3_3, _materialized_hypertable_4.agg_4_4, _materialized_hypertable_4.agg_4_5 + Startup Exclusion: true + Runtime Exclusion: false + Chunks excluded during startup: 0 + -> Index Scan using _hyper_4_6_chunk__materialized_hypertable_4_bucket_idx on _timescaledb_internal._hyper_4_6_chunk + Output: _hyper_4_6_chunk.bucket, _hyper_4_6_chunk.device_id, _hyper_4_6_chunk.agg_3_3, _hyper_4_6_chunk.agg_4_4, _hyper_4_6_chunk.agg_4_5 + Index Cond: (_hyper_4_6_chunk.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(3)), '-infinity'::timestamp with time zone)) + -> HashAggregate + Output: (time_bucket('@ 1 hour'::interval, jit_test_contagg.observation_time)), jit_test_contagg.device_id, avg(jit_test_contagg.metric), (max(jit_test_contagg.metric) - min(jit_test_contagg.metric)) + Group Key: time_bucket('@ 1 hour'::interval, jit_test_contagg.observation_time), jit_test_contagg.device_id + Filter: ((max(jit_test_contagg.metric) - min(jit_test_contagg.metric)) = '1800'::double precision) + -> Custom Scan (ChunkAppend) on public.jit_test_contagg + Output: time_bucket('@ 1 hour'::interval, jit_test_contagg.observation_time), jit_test_contagg.device_id, jit_test_contagg.metric + Startup Exclusion: true + Runtime Exclusion: false + Chunks excluded during startup: 4 + -> Index Scan using _hyper_3_5_chunk_jit_test_contagg_observation_time_idx on _timescaledb_internal._hyper_3_5_chunk + Output: _hyper_3_5_chunk.observation_time, _hyper_3_5_chunk.device_id, _hyper_3_5_chunk.metric + Index Cond: (_hyper_3_5_chunk.observation_time >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(3)), '-infinity'::timestamp with time zone)) +(33 rows) + +-- generate the results into two different files +\set ECHO errors +--TEST END-- diff --git a/tsl/test/sql/.gitignore b/tsl/test/sql/.gitignore index d1e0b1abf..2efa0b26f 100644 --- a/tsl/test/sql/.gitignore +++ b/tsl/test/sql/.gitignore @@ -7,3 +7,4 @@ /compression_permissions-*.sql /move-*.sql /reorder-*.sql +/jit-*.sql diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index 28a76258c..774382fac 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -29,6 +29,16 @@ set(TEST_TEMPLATES reorder.sql.in ) +# Check if PostgreSQL was compiled with JIT support +set(PG_CONFIG_H "${PG_INCLUDEDIR}/pg_config.h") +if (EXISTS ${PG_CONFIG_H}) + file(STRINGS "${PG_CONFIG_H}" PG_USE_LLVM + REGEX "^#[\t ]*define[\t ]+USE_LLVM[\t ]+1.*") + if (PG_USE_LLVM AND ${PG_VERSION_MAJOR} GREATER_EQUAL "11") + list(APPEND TEST_TEMPLATES jit.sql.in) + endif() +endif() + if (CMAKE_BUILD_TYPE MATCHES Debug) list(APPEND TEST_TEMPLATES #current_timestamp_mock available only in debug mode @@ -36,7 +46,6 @@ if (CMAKE_BUILD_TYPE MATCHES Debug) ) endif(CMAKE_BUILD_TYPE MATCHES Debug) - #compression only for PG > 9 if (${PG_VERSION_MAJOR} GREATER "9") diff --git a/tsl/test/sql/include/jit_cleanup.sql b/tsl/test/sql/include/jit_cleanup.sql new file mode 100644 index 000000000..c93904cc9 --- /dev/null +++ b/tsl/test/sql/include/jit_cleanup.sql @@ -0,0 +1,7 @@ +-- 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. + +DROP TABLE IF EXISTS jit_test CASCADE; +DROP TABLE IF EXISTS jit_test_interval CASCADE; +DROP TABLE IF EXISTS jit_test_contagg CASCADE; diff --git a/tsl/test/sql/include/jit_load.sql b/tsl/test/sql/include/jit_load.sql new file mode 100644 index 000000000..b966f3bec --- /dev/null +++ b/tsl/test/sql/include/jit_load.sql @@ -0,0 +1,37 @@ +-- 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. +CREATE TABLE jit_test(time timestamp NOT NULL, temp float); +SELECT create_hypertable('jit_test', 'time'); + +CREATE TABLE jit_test_interval(id int NOT NULL, temp float); +SELECT create_hypertable('jit_test_interval', 'id', chunk_time_interval => 10); + +CREATE TABLE jit_test_contagg ( + observation_time TIMESTAMPTZ NOT NULL, + device_id TEXT NOT NULL, + metric DOUBLE PRECISION NOT NULL, + PRIMARY KEY(observation_time, device_id) +); +SELECT table_name FROM create_hypertable('jit_test_contagg', 'observation_time'); + +CREATE VIEW jit_device_summary +WITH (timescaledb.continuous) +AS +SELECT + time_bucket('1 hour', observation_time) as bucket, + device_id, + avg(metric) as metric_avg, + max(metric)-min(metric) as metric_spread +FROM + jit_test_contagg +GROUP BY bucket, device_id; + +INSERT INTO jit_test_contagg +SELECT ts, 'device_1', (EXTRACT(EPOCH FROM ts)) from generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '30 minutes') ts; +INSERT INTO jit_test_contagg +SELECT ts, 'device_2', (EXTRACT(EPOCH FROM ts)) from generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '30 minutes') ts; + +ALTER VIEW jit_device_summary SET (timescaledb.max_interval_per_job = '60 day'); +SET timescaledb.current_timestamp_mock = '2018-12-31 00:00'; +REFRESH MATERIALIZED VIEW jit_device_summary; diff --git a/tsl/test/sql/include/jit_query.sql b/tsl/test/sql/include/jit_query.sql new file mode 100644 index 000000000..a8c9dfa62 --- /dev/null +++ b/tsl/test/sql/include/jit_query.sql @@ -0,0 +1,41 @@ +-- 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. + +-- github issue #1262 +-- +:PREFIX +INSERT INTO jit_test VALUES('2017-01-20T09:00:01', 22.5) RETURNING *; + +:PREFIX +INSERT INTO jit_test VALUES ('2017-01-20T09:00:02', 2), + ('2017-01-20T09:00:03', 5), + ('2017-01-20T09:00:04', 10); + +:PREFIX +SELECT * FROM jit_test WHERE temp > 5 and temp <= 10 ORDER BY time; + +-- update with iteration over chunks +-- +:PREFIX +INSERT INTO jit_test_interval (SELECT x, x / 2.3 FROM generate_series(0, 100) x) RETURNING *; + +:PREFIX +SELECT * FROM jit_test_interval WHERE id >= 23 and id < 73 ORDER BY id; + +:PREFIX +UPDATE jit_test_interval SET temp = temp * 2.3 WHERE id >= 23 and id < 73; + +:PREFIX +SELECT * FROM jit_test_interval ORDER BY id; + +:PREFIX +SELECT time_bucket(10, id), avg(temp) +FROM jit_test_interval +GROUP BY 1 +ORDER BY 1; + +-- test continuous aggregates usage with forced jit (based on continuous_aggs_usage.sql) +-- +:PREFIX +SELECT * FROM jit_device_summary WHERE metric_spread = 1800 ORDER BY bucket DESC, device_id LIMIT 10; diff --git a/tsl/test/sql/jit.sql.in b/tsl/test/sql/jit.sql.in new file mode 100644 index 000000000..6e87fae58 --- /dev/null +++ b/tsl/test/sql/jit.sql.in @@ -0,0 +1,59 @@ +-- 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 jit +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('include/%s_cleanup.sql', :'TEST_BASE_NAME') as "TEST_CLEANUP_NAME", + format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_OPTIMIZED", + format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_UNOPTIMIZED" +\gset +SELECT format('\! diff -u --label "Unoptimized results" --label "Optimized results" %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_OPTIMIZED') as "DIFF_CMD" +\gset + +-- enable all jit optimizations +-- +-- disable jit_tuple_deforming for PG11 as a temporary solution +-- until it fixed +-- +SET jit=on; +SET jit_above_cost=0; +SET jit_inline_above_cost=0; +SET jit_optimize_above_cost=0; +SELECT + CASE WHEN current_setting('server_version_num')::int < 120000 + THEN 0 ELSE 1 + END AS "USE_JIT_DEFORMING" +\gset +SET jit_tuple_deforming=:USE_JIT_DEFORMING; + +\ir :TEST_LOAD_NAME +\set PREFIX 'EXPLAIN (VERBOSE, TIMING OFF, COSTS OFF, SUMMARY OFF)' +\ir :TEST_QUERY_NAME + +-- generate the results into two different files +\set ECHO errors +SET client_min_messages TO error; +\set PREFIX '' + +-- get query results with jit enabled +\o :TEST_RESULTS_OPTIMIZED +\ir :TEST_QUERY_NAME +\o + +-- disable jit optimizations and repeat +SET jit=off; + +\o /dev/null +\ir :TEST_CLEANUP_NAME +\ir :TEST_LOAD_NAME +\o :TEST_RESULTS_UNOPTIMIZED +\ir :TEST_QUERY_NAME +\o + +-- compare jit vs non-jit output +:DIFF_CMD + +\set ECHO queries +\qecho '--TEST END--'