Sven Klemm c5c13415f0 Use ChunkAppend to replace Append nodes
This patch makes TimescaleDB use ChunkAppend in places where it
used to used to use ConstraintAwareAppend before.
ConstraintAwareAppend will still be used for MergeAppend nodes
that cannot be changed to Ordered Append or when ChunkAppend is
disabled.
When a query on a hypertable is identified as benefitting from
execution exclusion Append nodes will be replaced by ChunkAppend
nodes.
This will enable the use of runtime exclusion for joins, lateral
joins, subqueries and correlated subqueries.
2019-06-20 14:20:46 +02:00

231 lines
15 KiB
Plaintext

-- This file and its contents are licensed under the Apache License 2.0.
-- Please see the included NOTICE for copyright information and
-- LICENSE-APACHE for a copy of the license.
\o /dev/null
\ir include/insert_two_partitions.sql
-- This file and its contents are licensed under the Apache License 2.0.
-- Please see the included NOTICE for copyright information and
-- LICENSE-APACHE for a copy of the license.
CREATE TABLE PUBLIC."two_Partitions" (
"timeCustom" BIGINT NOT NULL,
device_id TEXT NOT NULL,
series_0 DOUBLE PRECISION NULL,
series_1 DOUBLE PRECISION NULL,
series_2 DOUBLE PRECISION NULL,
series_bool BOOLEAN NULL
);
CREATE INDEX ON PUBLIC."two_Partitions" (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, device_id);
SELECT * FROM create_hypertable('"public"."two_Partitions"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2, chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
\set QUIET off
BEGIN;
\COPY public."two_Partitions" FROM 'data/ds1_dev1_1.tsv' NULL AS '';
COMMIT;
INSERT INTO public."two_Partitions"("timeCustom", device_id, series_0, series_1) VALUES
(1257987600000000000, 'dev1', 1.5, 1),
(1257987600000000000, 'dev1', 1.5, 2),
(1257894000000000000, 'dev2', 1.5, 1),
(1257894002000000000, 'dev1', 2.5, 3);
INSERT INTO "two_Partitions"("timeCustom", device_id, series_0, series_1) VALUES
(1257894000000000000, 'dev2', 1.5, 2);
\set QUIET on
\o
SELECT * FROM "two_Partitions" ORDER BY "timeCustom", device_id, series_0, series_1;
timeCustom | device_id | series_0 | series_1 | series_2 | series_bool
---------------------+-----------+----------+----------+----------+-------------
1257894000000000000 | dev1 | 1.5 | 1 | 2 | t
1257894000000000000 | dev1 | 1.5 | 2 | |
1257894000000000000 | dev2 | 1.5 | 1 | |
1257894000000000000 | dev2 | 1.5 | 2 | |
1257894000000001000 | dev1 | 2.5 | 3 | |
1257894001000000000 | dev1 | 3.5 | 4 | |
1257894002000000000 | dev1 | 2.5 | 3 | |
1257894002000000000 | dev1 | 5.5 | 6 | | t
1257894002000000000 | dev1 | 5.5 | 7 | | f
1257897600000000000 | dev1 | 4.5 | 5 | | f
1257987600000000000 | dev1 | 1.5 | 1 | |
1257987600000000000 | dev1 | 1.5 | 2 | |
(12 rows)
DELETE FROM "two_Partitions" WHERE series_0 = 1.5;
DELETE FROM "two_Partitions" WHERE series_0 = 100;
SELECT * FROM "two_Partitions" ORDER BY "timeCustom", device_id, series_0, series_1;
timeCustom | device_id | series_0 | series_1 | series_2 | series_bool
---------------------+-----------+----------+----------+----------+-------------
1257894000000001000 | dev1 | 2.5 | 3 | |
1257894001000000000 | dev1 | 3.5 | 4 | |
1257894002000000000 | dev1 | 2.5 | 3 | |
1257894002000000000 | dev1 | 5.5 | 6 | | t
1257894002000000000 | dev1 | 5.5 | 7 | | f
1257897600000000000 | dev1 | 4.5 | 5 | | f
(6 rows)
-- Make sure DELETE isn't optimized if it includes Append plans
-- Need to turn of nestloop to make append appear the same on PG96 and PG10
set enable_nestloop = 'off';
CREATE OR REPLACE FUNCTION series_val()
RETURNS integer LANGUAGE PLPGSQL STABLE AS
$BODY$
BEGIN
RETURN 5;
END;
$BODY$;
-- ConstraintAwareAppend applied for SELECT
EXPLAIN (costs off)
SELECT FROM "two_Partitions"
WHERE series_1 IN (SELECT series_1 FROM "two_Partitions" WHERE series_1 > series_val());
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------
Hash Join
Hash Cond: ("two_Partitions".series_1 = "two_Partitions_1".series_1)
-> Custom Scan (ChunkAppend) on "two_Partitions"
Chunks excluded during startup: 0
-> Index Only Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_1_chunk
Index Cond: (series_1 > (series_val())::double precision)
-> Index Only Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_2_chunk
Index Cond: (series_1 > (series_val())::double precision)
-> Index Only Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_3_chunk
Index Cond: (series_1 > (series_val())::double precision)
-> Index Only Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_4_chunk
Index Cond: (series_1 > (series_val())::double precision)
-> Hash
-> HashAggregate
Group Key: "two_Partitions_1".series_1
-> Custom Scan (ChunkAppend) on "two_Partitions" "two_Partitions_1"
Chunks excluded during startup: 0
-> Index Only Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_1_chunk _hyper_1_1_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Only Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_2_chunk _hyper_1_2_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Only Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_3_chunk _hyper_1_3_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Only Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_4_chunk _hyper_1_4_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
(25 rows)
-- ConstraintAwareAppend NOT applied for DELETE
EXPLAIN (costs off)
DELETE FROM "two_Partitions"
WHERE series_1 IN (SELECT series_1 FROM "two_Partitions" WHERE series_1 > series_val());
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------
Delete on "two_Partitions"
Delete on "two_Partitions"
Delete on _hyper_1_1_chunk
Delete on _hyper_1_2_chunk
Delete on _hyper_1_3_chunk
Delete on _hyper_1_4_chunk
-> Hash Join
Hash Cond: ("two_Partitions_1".series_1 = "two_Partitions".series_1)
-> HashAggregate
Group Key: "two_Partitions_1".series_1
-> Append
-> Seq Scan on "two_Partitions" "two_Partitions_1"
Filter: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_1_chunk _hyper_1_1_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_2_chunk _hyper_1_2_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_3_chunk _hyper_1_3_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_4_chunk _hyper_1_4_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Hash
-> Seq Scan on "two_Partitions"
-> Hash Join
Hash Cond: (_hyper_1_1_chunk.series_1 = "two_Partitions_1".series_1)
-> Seq Scan on _hyper_1_1_chunk
-> Hash
-> HashAggregate
Group Key: "two_Partitions_1".series_1
-> Append
-> Seq Scan on "two_Partitions" "two_Partitions_1"
Filter: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_1_chunk _hyper_1_1_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_2_chunk _hyper_1_2_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_3_chunk _hyper_1_3_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_4_chunk _hyper_1_4_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Hash Join
Hash Cond: (_hyper_1_2_chunk.series_1 = "two_Partitions_1".series_1)
-> Seq Scan on _hyper_1_2_chunk
-> Hash
-> HashAggregate
Group Key: "two_Partitions_1".series_1
-> Append
-> Seq Scan on "two_Partitions" "two_Partitions_1"
Filter: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_1_chunk _hyper_1_1_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_2_chunk _hyper_1_2_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_3_chunk _hyper_1_3_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_4_chunk _hyper_1_4_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Hash Join
Hash Cond: (_hyper_1_3_chunk.series_1 = "two_Partitions_1".series_1)
-> Seq Scan on _hyper_1_3_chunk
-> Hash
-> HashAggregate
Group Key: "two_Partitions_1".series_1
-> Append
-> Seq Scan on "two_Partitions" "two_Partitions_1"
Filter: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_1_chunk _hyper_1_1_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_2_chunk _hyper_1_2_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_3_chunk _hyper_1_3_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_4_chunk _hyper_1_4_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Hash Join
Hash Cond: (_hyper_1_4_chunk.series_1 = "two_Partitions_1".series_1)
-> Seq Scan on _hyper_1_4_chunk
-> Hash
-> HashAggregate
Group Key: "two_Partitions_1".series_1
-> Append
-> Seq Scan on "two_Partitions" "two_Partitions_1"
Filter: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_1_chunk _hyper_1_1_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_2_chunk _hyper_1_2_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_3_chunk _hyper_1_3_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" on _hyper_1_4_chunk _hyper_1_4_chunk_1
Index Cond: (series_1 > (series_val())::double precision)
(91 rows)
SELECT * FROM "two_Partitions" ORDER BY "timeCustom", device_id, series_0, series_1;
timeCustom | device_id | series_0 | series_1 | series_2 | series_bool
---------------------+-----------+----------+----------+----------+-------------
1257894000000001000 | dev1 | 2.5 | 3 | |
1257894001000000000 | dev1 | 3.5 | 4 | |
1257894002000000000 | dev1 | 2.5 | 3 | |
1257894002000000000 | dev1 | 5.5 | 6 | | t
1257894002000000000 | dev1 | 5.5 | 7 | | f
1257897600000000000 | dev1 | 4.5 | 5 | | f
(6 rows)
DELETE FROM "two_Partitions"
WHERE series_1 IN (SELECT series_1 FROM "two_Partitions" WHERE series_1 > series_val());
SELECT * FROM "two_Partitions" ORDER BY "timeCustom", device_id, series_0, series_1;
timeCustom | device_id | series_0 | series_1 | series_2 | series_bool
---------------------+-----------+----------+----------+----------+-------------
1257894000000001000 | dev1 | 2.5 | 3 | |
1257894001000000000 | dev1 | 3.5 | 4 | |
1257894002000000000 | dev1 | 2.5 | 3 | |
1257897600000000000 | dev1 | 4.5 | 5 | | f
(4 rows)