From 676d1fb1f1f82f34ae5cdad96022796682215f27 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Tue, 15 Nov 2022 18:03:05 +0400 Subject: [PATCH] Fix const null clauses in runtime chunk exclusion The code we inherited from postgres expects that if we have a const null or false clause, it's going to be the single one, but that's not true for runtime chunk exclusion because we don't try to fold such restrictinfos after evaluating the mutable functions. Fix it to also work for multiple restrictinfos. --- src/nodes/chunk_append/exec.c | 22 +-- test/expected/null_exclusion.out | 126 ++++++++++++++++++ test/sql/CMakeLists.txt | 1 + test/sql/null_exclusion.sql | 31 +++++ ...sparent_decompression_ordered_index-12.out | 50 ++++--- ...sparent_decompression_ordered_index-13.out | 50 ++++--- ...sparent_decompression_ordered_index-14.out | 50 ++++--- ...sparent_decompression_ordered_index-15.out | 50 ++++--- ...sparent_decompression_ordered_index.sql.in | 6 + 9 files changed, 297 insertions(+), 89 deletions(-) create mode 100644 test/expected/null_exclusion.out create mode 100644 test/sql/null_exclusion.sql diff --git a/src/nodes/chunk_append/exec.c b/src/nodes/chunk_append/exec.c index b8ba3a54e..fe9dd39ca 100644 --- a/src/nodes/chunk_append/exec.c +++ b/src/nodes/chunk_append/exec.c @@ -954,17 +954,21 @@ static bool can_exclude_chunk(List *constraints, List *baserestrictinfo) { /* - * Regardless of the setting of constraint_exclusion, detect - * constant-FALSE-or-NULL restriction clauses. Because const-folding will - * reduce "anything AND FALSE" to just "FALSE", any such case should - * result in exactly one baserestrictinfo entry. This doesn't fire very - * often, but it seems cheap enough to be worth doing anyway. (Without - * this, we'd miss some optimizations that 9.5 and earlier found via much - * more roundabout methods.) + * Detect constant-FALSE-or-NULL restriction clauses. If we have such a + * clause, no rows from the chunk are going to match. Unlike the postgres + * analog of this code in relation_excluded_by_constraints, we can't expect + * a single const false restrictinfo in this case, because we don't try to + * fold the restrictinfos after evaluating the mutable functions. + * We have to check this separately from the subsequent predicate_refuted_by. + * That function can also work with the normal CHECK constraints, and they + * don't fail if the constraint evaluates to null given the restriction info. + * That's why it has to prove that the CHECK constraint evaluates to false, + * and this doesn't follow from having a const null restrictinfo. */ - if (list_length(baserestrictinfo) == 1) + ListCell *lc; + foreach (lc, baserestrictinfo) { - RestrictInfo *rinfo = (RestrictInfo *) linitial(baserestrictinfo); + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); Expr *clause = rinfo->clause; if (clause && IsA(clause, Const) && diff --git a/test/expected/null_exclusion.out b/test/expected/null_exclusion.out new file mode 100644 index 000000000..9c4242ab3 --- /dev/null +++ b/test/expected/null_exclusion.out @@ -0,0 +1,126 @@ +-- 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 metrics(ts timestamp, id int, value float); +select create_hypertable('metrics', 'ts'); +WARNING: column type "timestamp without time zone" used for "ts" does not follow best practices +NOTICE: adding not-null constraint to column "ts" + create_hypertable +---------------------- + (1,public,metrics,t) +(1 row) + +insert into metrics values ('2022-02-02 02:02:02', 2, 2.), + ('2023-03-03 03:03:03', 3, 3.); +analyze metrics; +-- non-const condition +explain (analyze, costs off, summary off, timing off) +select * from metrics +where ts >= (select max(ts) from metrics); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics (actual rows=1 loops=1) + Chunks excluded during runtime: 1 + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on metrics metrics_1 (actual rows=1 loops=1) + Order: metrics_1.ts DESC + -> Index Only Scan using _hyper_1_2_chunk_metrics_ts_idx on _hyper_1_2_chunk _hyper_1_2_chunk_1 (actual rows=1 loops=1) + Index Cond: (ts IS NOT NULL) + Heap Fetches: 1 + -> Index Only Scan using _hyper_1_1_chunk_metrics_ts_idx on _hyper_1_1_chunk _hyper_1_1_chunk_1 (never executed) + Index Cond: (ts IS NOT NULL) + Heap Fetches: 0 + -> Seq Scan on _hyper_1_1_chunk (never executed) + Filter: (ts >= $1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=1 loops=1) + Filter: (ts >= $1) +(18 rows) + +-- two non-const conditions +explain (analyze, costs off, summary off, timing off) +select * from metrics +where ts >= (select max(ts) from metrics) + and id = 1; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics (actual rows=0 loops=1) + Chunks excluded during runtime: 1 + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on metrics metrics_1 (actual rows=1 loops=1) + Order: metrics_1.ts DESC + -> Index Only Scan using _hyper_1_2_chunk_metrics_ts_idx on _hyper_1_2_chunk _hyper_1_2_chunk_1 (actual rows=1 loops=1) + Index Cond: (ts IS NOT NULL) + Heap Fetches: 1 + -> Index Only Scan using _hyper_1_1_chunk_metrics_ts_idx on _hyper_1_1_chunk _hyper_1_1_chunk_1 (never executed) + Index Cond: (ts IS NOT NULL) + Heap Fetches: 0 + -> Seq Scan on _hyper_1_1_chunk (never executed) + Filter: ((ts >= $1) AND (id = 1)) + -> Seq Scan on _hyper_1_2_chunk (actual rows=0 loops=1) + Filter: ((ts >= $1) AND (id = 1)) + Rows Removed by Filter: 1 +(19 rows) + +-- condition that becomes const null after evaluating the param +explain (analyze, costs off, summary off, timing off) +select * from metrics +where ts >= (select max(ts) from metrics where id = -1); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics (actual rows=0 loops=1) + Chunks excluded during runtime: 2 + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=0 loops=1) + -> Custom Scan (ChunkAppend) on metrics metrics_1 (actual rows=0 loops=1) + Order: metrics_1.ts DESC + -> Index Scan using _hyper_1_2_chunk_metrics_ts_idx on _hyper_1_2_chunk _hyper_1_2_chunk_1 (actual rows=0 loops=1) + Index Cond: (ts IS NOT NULL) + Filter: (id = '-1'::integer) + Rows Removed by Filter: 1 + -> Index Scan using _hyper_1_1_chunk_metrics_ts_idx on _hyper_1_1_chunk _hyper_1_1_chunk_1 (actual rows=0 loops=1) + Index Cond: (ts IS NOT NULL) + Filter: (id = '-1'::integer) + Rows Removed by Filter: 1 + -> Seq Scan on _hyper_1_1_chunk (never executed) + Filter: (ts >= $1) + -> Seq Scan on _hyper_1_2_chunk (never executed) + Filter: (ts >= $1) +(20 rows) + +-- const null condition and some other condition +explain (analyze, costs off, summary off, timing off) +select * from metrics +where ts >= (select max(ts) from metrics where id = -1) + and id = 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics (actual rows=0 loops=1) + Chunks excluded during runtime: 2 + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=0 loops=1) + -> Custom Scan (ChunkAppend) on metrics metrics_1 (actual rows=0 loops=1) + Order: metrics_1.ts DESC + -> Index Scan using _hyper_1_2_chunk_metrics_ts_idx on _hyper_1_2_chunk _hyper_1_2_chunk_1 (actual rows=0 loops=1) + Index Cond: (ts IS NOT NULL) + Filter: (id = '-1'::integer) + Rows Removed by Filter: 1 + -> Index Scan using _hyper_1_1_chunk_metrics_ts_idx on _hyper_1_1_chunk _hyper_1_1_chunk_1 (actual rows=0 loops=1) + Index Cond: (ts IS NOT NULL) + Filter: (id = '-1'::integer) + Rows Removed by Filter: 1 + -> Seq Scan on _hyper_1_1_chunk (never executed) + Filter: ((ts >= $1) AND (id = 1)) + -> Seq Scan on _hyper_1_2_chunk (never executed) + Filter: ((ts >= $1) AND (id = 1)) +(20 rows) + diff --git a/test/sql/CMakeLists.txt b/test/sql/CMakeLists.txt index 2bb76c5a0..658de3cf3 100644 --- a/test/sql/CMakeLists.txt +++ b/test/sql/CMakeLists.txt @@ -30,6 +30,7 @@ set(TEST_FILES insert_returning.sql lateral.sql misc.sql + null_exclusion.sql partition.sql partitioning.sql pg_dump_unprivileged.sql diff --git a/test/sql/null_exclusion.sql b/test/sql/null_exclusion.sql new file mode 100644 index 000000000..c77206289 --- /dev/null +++ b/test/sql/null_exclusion.sql @@ -0,0 +1,31 @@ +-- 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 metrics(ts timestamp, id int, value float); +select create_hypertable('metrics', 'ts'); +insert into metrics values ('2022-02-02 02:02:02', 2, 2.), + ('2023-03-03 03:03:03', 3, 3.); +analyze metrics; + +-- non-const condition +explain (analyze, costs off, summary off, timing off) +select * from metrics +where ts >= (select max(ts) from metrics); + +-- two non-const conditions +explain (analyze, costs off, summary off, timing off) +select * from metrics +where ts >= (select max(ts) from metrics) + and id = 1; + +-- condition that becomes const null after evaluating the param +explain (analyze, costs off, summary off, timing off) +select * from metrics +where ts >= (select max(ts) from metrics where id = -1); + +-- const null condition and some other condition +explain (analyze, costs off, summary off, timing off) +select * from metrics +where ts >= (select max(ts) from metrics where id = -1) + and id = 1; diff --git a/tsl/test/expected/transparent_decompression_ordered_index-12.out b/tsl/test/expected/transparent_decompression_ordered_index-12.out index 67b599c4e..182686eae 100644 --- a/tsl/test/expected/transparent_decompression_ordered_index-12.out +++ b/tsl/test/expected/transparent_decompression_ordered_index-12.out @@ -95,6 +95,16 @@ ORDER BY c.id; \set ECHO none -- diff compressed and uncompressed results :DIFF_CMD +-- This is to illustrate that we have some null device_id values. This fact +-- might influence the runtime chunk exclusion when doing joins on device_id. +select count(*) from metrics_ordered_idx +where extract(minute from time) = 0 and device_id is null +; + count +------- + 1 +(1 row) + \set PREFIX 'EXPLAIN (analyze, costs off, timing off, summary off)' \set PREFIX_VERBOSE 'EXPLAIN (analyze, costs off, timing off, summary off, verbose)' -- we disable parallelism here otherwise EXPLAIN ANALYZE output @@ -328,20 +338,20 @@ WHERE extract(minute FROM d.time) = 0; -> Custom Scan (ChunkAppend) on metrics_ordered_idx m_1 (actual rows=0 loops=389) Order: m_1."time" DESC Hypertables excluded during runtime: 0 - -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) (48 rows) @@ -389,20 +399,20 @@ WHERE extract(minute FROM d.time) = 0; -> Custom Scan (ChunkAppend) on metrics_ordered_idx m_1 (actual rows=0 loops=389) Order: m_1."time" DESC Hypertables excluded during runtime: 0 - -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) (44 rows) diff --git a/tsl/test/expected/transparent_decompression_ordered_index-13.out b/tsl/test/expected/transparent_decompression_ordered_index-13.out index 2cdbcbb77..6d9bbd815 100644 --- a/tsl/test/expected/transparent_decompression_ordered_index-13.out +++ b/tsl/test/expected/transparent_decompression_ordered_index-13.out @@ -95,6 +95,16 @@ ORDER BY c.id; \set ECHO none -- diff compressed and uncompressed results :DIFF_CMD +-- This is to illustrate that we have some null device_id values. This fact +-- might influence the runtime chunk exclusion when doing joins on device_id. +select count(*) from metrics_ordered_idx +where extract(minute from time) = 0 and device_id is null +; + count +------- + 1 +(1 row) + \set PREFIX 'EXPLAIN (analyze, costs off, timing off, summary off)' \set PREFIX_VERBOSE 'EXPLAIN (analyze, costs off, timing off, summary off, verbose)' -- we disable parallelism here otherwise EXPLAIN ANALYZE output @@ -328,20 +338,20 @@ WHERE extract(minute FROM d.time) = 0; -> Custom Scan (ChunkAppend) on metrics_ordered_idx m_1 (actual rows=0 loops=389) Order: m_1."time" DESC Hypertables excluded during runtime: 0 - -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) (48 rows) @@ -389,20 +399,20 @@ WHERE extract(minute FROM d.time) = 0; -> Custom Scan (ChunkAppend) on metrics_ordered_idx m_1 (actual rows=0 loops=389) Order: m_1."time" DESC Hypertables excluded during runtime: 0 - -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) (44 rows) diff --git a/tsl/test/expected/transparent_decompression_ordered_index-14.out b/tsl/test/expected/transparent_decompression_ordered_index-14.out index 1ea91d4c2..7b540fec4 100644 --- a/tsl/test/expected/transparent_decompression_ordered_index-14.out +++ b/tsl/test/expected/transparent_decompression_ordered_index-14.out @@ -95,6 +95,16 @@ ORDER BY c.id; \set ECHO none -- diff compressed and uncompressed results :DIFF_CMD +-- This is to illustrate that we have some null device_id values. This fact +-- might influence the runtime chunk exclusion when doing joins on device_id. +select count(*) from metrics_ordered_idx +where extract(minute from time) = 0 and device_id is null +; + count +------- + 1 +(1 row) + \set PREFIX 'EXPLAIN (analyze, costs off, timing off, summary off)' \set PREFIX_VERBOSE 'EXPLAIN (analyze, costs off, timing off, summary off, verbose)' -- we disable parallelism here otherwise EXPLAIN ANALYZE output @@ -328,20 +338,20 @@ WHERE extract(minute FROM d.time) = 0; -> Custom Scan (ChunkAppend) on metrics_ordered_idx m_1 (actual rows=0 loops=389) Order: m_1."time" DESC Hypertables excluded during runtime: 0 - -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) (48 rows) @@ -389,20 +399,20 @@ WHERE extract(minute FROM d.time) = 0; -> Custom Scan (ChunkAppend) on metrics_ordered_idx m_1 (actual rows=0 loops=389) Order: m_1."time" DESC Hypertables excluded during runtime: 0 - -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) (44 rows) diff --git a/tsl/test/expected/transparent_decompression_ordered_index-15.out b/tsl/test/expected/transparent_decompression_ordered_index-15.out index f10242f21..57e5f5a5b 100644 --- a/tsl/test/expected/transparent_decompression_ordered_index-15.out +++ b/tsl/test/expected/transparent_decompression_ordered_index-15.out @@ -95,6 +95,16 @@ ORDER BY c.id; \set ECHO none -- diff compressed and uncompressed results :DIFF_CMD +-- This is to illustrate that we have some null device_id values. This fact +-- might influence the runtime chunk exclusion when doing joins on device_id. +select count(*) from metrics_ordered_idx +where extract(minute from time) = 0 and device_id is null +; + count +------- + 1 +(1 row) + \set PREFIX 'EXPLAIN (analyze, costs off, timing off, summary off)' \set PREFIX_VERBOSE 'EXPLAIN (analyze, costs off, timing off, summary off, verbose)' -- we disable parallelism here otherwise EXPLAIN ANALYZE output @@ -329,20 +339,20 @@ WHERE extract(minute FROM d.time) = 0; -> Custom Scan (ChunkAppend) on metrics_ordered_idx m_1 (actual rows=0 loops=389) Order: m_1."time" DESC Hypertables excluded during runtime: 0 - -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) (48 rows) @@ -391,20 +401,20 @@ WHERE extract(minute FROM d.time) = 0; -> Custom Scan (ChunkAppend) on metrics_ordered_idx m_1 (actual rows=0 loops=389) Order: m_1."time" DESC Hypertables excluded during runtime: 0 - -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_5_chunk m_2 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_10_chunk__compressed_hypertable_2_device_id_de on compress_hyper_2_10_chunk compress_hyper_2_10_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk m_3 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_9_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_9_chunk compress_hyper_2_9_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=389) - -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=389) + -> Custom Scan (DecompressChunk) on _hyper_1_3_chunk m_4 (actual rows=0 loops=388) + -> Index Scan Backward using compress_hyper_2_8_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_8_chunk compress_hyper_2_8_chunk_1 (actual rows=0 loops=388) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk m_5 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_7_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_7_chunk compress_hyper_2_7_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=305) - -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=305) + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk m_6 (actual rows=0 loops=304) + -> Index Scan Backward using compress_hyper_2_6_chunk__compressed_hypertable_2_device_id_dev on compress_hyper_2_6_chunk compress_hyper_2_6_chunk_1 (actual rows=0 loops=304) Index Cond: ((device_id = d.device_id) AND (device_id_peer = 3)) (45 rows) diff --git a/tsl/test/sql/transparent_decompression_ordered_index.sql.in b/tsl/test/sql/transparent_decompression_ordered_index.sql.in index 848219c04..c4214aa40 100644 --- a/tsl/test/sql/transparent_decompression_ordered_index.sql.in +++ b/tsl/test/sql/transparent_decompression_ordered_index.sql.in @@ -118,6 +118,12 @@ RESET client_min_messages; -- diff compressed and uncompressed results :DIFF_CMD +-- This is to illustrate that we have some null device_id values. This fact +-- might influence the runtime chunk exclusion when doing joins on device_id. +select count(*) from metrics_ordered_idx +where extract(minute from time) = 0 and device_id is null +; + \set PREFIX 'EXPLAIN (analyze, costs off, timing off, summary off)' \set PREFIX_VERBOSE 'EXPLAIN (analyze, costs off, timing off, summary off, verbose)' -- we disable parallelism here otherwise EXPLAIN ANALYZE output