diff --git a/tsl/src/nodes/decompress_chunk/decompress_chunk.c b/tsl/src/nodes/decompress_chunk/decompress_chunk.c index ac2c7873422..dcf932b3431 100644 --- a/tsl/src/nodes/decompress_chunk/decompress_chunk.c +++ b/tsl/src/nodes/decompress_chunk/decompress_chunk.c @@ -429,13 +429,22 @@ build_compressioninfo(PlannerInfo *root, const Hypertable *ht, const Chunk *chun static void cost_decompress_chunk(PlannerInfo *root, Path *path, Path *compressed_path) { + /* Set the row number estimate. */ + if (path->param_info != NULL) + { + path->rows = path->param_info->ppi_rows; + } + else + { + path->rows = path->parent->rows; + } + /* startup_cost is cost before fetching first tuple */ if (compressed_path->rows > 0) path->startup_cost = compressed_path->total_cost / compressed_path->rows; /* total_cost is cost for fetching all tuples */ path->total_cost = compressed_path->total_cost + path->rows * cpu_tuple_cost; - path->rows = compressed_path->rows * TARGET_COMPRESSED_BATCH_SIZE; } /* Smoothstep function S1 (the h01 cubic Hermite spline). */ @@ -866,8 +875,12 @@ ts_decompress_chunk_generate_paths(PlannerInfo *root, RelOptInfo *chunk_rel, con compressed_rel->consider_parallel = chunk_rel->consider_parallel; /* translate chunk_rel->baserestrictinfo */ pushdown_quals(root, compression_info->settings, chunk_rel, compressed_rel, consider_partial); + set_baserel_size_estimates(root, compressed_rel); - double new_row_estimate = compressed_rel->rows * TARGET_COMPRESSED_BATCH_SIZE; + const double new_tuples_estimate = compressed_rel->rows * TARGET_COMPRESSED_BATCH_SIZE; + const double new_rows_estimate = + new_tuples_estimate * + clauselist_selectivity(root, chunk_rel->baserestrictinfo, 0, JOIN_INNER, NULL); if (!compression_info->single_chunk) { @@ -876,10 +889,19 @@ ts_decompress_chunk_generate_paths(PlannerInfo *root, RelOptInfo *chunk_rel, con Assert(chunk_info->parent_reloid == ht->main_table_relid); ht_relid = chunk_info->parent_relid; RelOptInfo *hypertable_rel = root->simple_rel_array[ht_relid]; - hypertable_rel->rows += (new_row_estimate - chunk_rel->rows); + hypertable_rel->rows = + clamp_row_est(hypertable_rel->rows + new_rows_estimate - chunk_rel->rows); + hypertable_rel->tuples = + clamp_row_est(hypertable_rel->tuples + new_tuples_estimate - chunk_rel->tuples); } - chunk_rel->rows = new_row_estimate; + /* + * Note that we can be overwriting the estimate for uncompressed chunk part of a + * partial chunk here, but the paths for the uncompressed part were already + * built, so it is OK. + */ + chunk_rel->tuples = new_tuples_estimate; + chunk_rel->rows = new_rows_estimate; create_compressed_scan_paths(root, compressed_rel, compression_info, &sort_info); diff --git a/tsl/src/nodes/decompress_chunk/qual_pushdown.c b/tsl/src/nodes/decompress_chunk/qual_pushdown.c index 514202793e9..2fbb07cbf16 100644 --- a/tsl/src/nodes/decompress_chunk/qual_pushdown.c +++ b/tsl/src/nodes/decompress_chunk/qual_pushdown.c @@ -96,6 +96,17 @@ pushdown_quals(PlannerInfo *root, CompressionSettings *settings, RelOptInfo *chu { decompress_clauses = lappend(decompress_clauses, ri); } + + if (context.can_pushdown && context.needs_recheck) + { + /* + * If we managed to push down the comparison of orderby column + * to the compressed scan, most matched batches are likely to + * match entirely, so the selectivity of the recheck will be + * close to 1. + */ + ri->norm_selec = 1; + } } chunk_rel->baserestrictinfo = decompress_clauses; } diff --git a/tsl/test/expected/transparent_decompression_ordered_index-15.out b/tsl/test/expected/transparent_decompression_ordered_index-15.out index 6e0802e055b..e130f2d092c 100644 --- a/tsl/test/expected/transparent_decompression_ordered_index-15.out +++ b/tsl/test/expected/transparent_decompression_ordered_index-15.out @@ -690,22 +690,20 @@ JOIN LATERAL WHERE node = f1.device_id) q ON met.device_id = q.node and met.device_id_peer = q.device_id_peer and met.v0 = q.v0 and met.v0 > 2 and time = '2018-01-19 20:00:00-05'; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop (actual rows=1 loops=1) - Join Filter: (nodetime.node = met.device_id) + Join Filter: ("*VALUES*".column1 = nodetime.node) -> Nested Loop (actual rows=1 loops=1) - Join Filter: (nodetime.node = "*VALUES*".column1) - Rows Removed by Join Filter: 1 - -> Seq Scan on nodetime (actual rows=1 loops=1) -> Values Scan on "*VALUES*" (actual rows=2 loops=1) - -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk met (actual rows=1 loops=1) - Filter: ("*VALUES*".column3 = v0) - Rows Removed by Filter: 47 - Vectorized Filter: ((v0 > 2) AND ("time" = 'Fri Jan 19 17:00:00 2018 PST'::timestamp with time zone)) - -> Index Scan using compress_hyper_2_9_chunk_device_id_device_id_peer__ts_meta__idx on compress_hyper_2_9_chunk (actual rows=1 loops=1) - Index Cond: ((device_id = "*VALUES*".column1) AND (device_id_peer = "*VALUES*".column2) AND (_ts_meta_min_1 <= 'Fri Jan 19 17:00:00 2018 PST'::timestamp with time zone) AND (_ts_meta_max_1 >= 'Fri Jan 19 17:00:00 2018 PST'::timestamp with time zone)) -(13 rows) + -> Custom Scan (DecompressChunk) on _hyper_1_4_chunk met (actual rows=0 loops=2) + Filter: ("*VALUES*".column3 = v0) + Rows Removed by Filter: 24 + Vectorized Filter: ((v0 > 2) AND ("time" = 'Fri Jan 19 17:00:00 2018 PST'::timestamp with time zone)) + -> Index Scan using compress_hyper_2_9_chunk_device_id_device_id_peer__ts_meta__idx on compress_hyper_2_9_chunk (actual rows=0 loops=2) + Index Cond: ((device_id = "*VALUES*".column1) AND (device_id_peer = "*VALUES*".column2) AND (_ts_meta_min_1 <= 'Fri Jan 19 17:00:00 2018 PST'::timestamp with time zone) AND (_ts_meta_max_1 >= 'Fri Jan 19 17:00:00 2018 PST'::timestamp with time zone)) + -> Seq Scan on nodetime (actual rows=1 loops=1) +(11 rows) -- filter on compressed attr (v0) with seqscan enabled and indexscan -- disabled. filters on compressed attr should be above the seq scan. @@ -841,24 +839,22 @@ GROUP BY m.device_id, ORDER BY 1, 2, 3; - QUERY PLAN ----------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------- Sort (actual rows=0 loops=1) Sort Key: m.device_id, d.v0, (count(*)) Sort Method: quicksort -> HashAggregate (actual rows=0 loops=1) Group Key: m.device_id, d.v0 Batches: 1 - -> Hash Join (actual rows=0 loops=1) - Hash Cond: ((d.device_id = m.device_id) AND (d."time" = m."time")) + -> Nested Loop (actual rows=0 loops=1) -> Custom Scan (ConstraintAwareAppend) (actual rows=0 loops=1) Hypertable: metrics_ordered_idx Chunks excluded during startup: 2 - -> Hash (never executed) - -> Custom Scan (ConstraintAwareAppend) (never executed) - Hypertable: metrics_ordered_idx - Chunks excluded during startup: 2 -(15 rows) + -> Custom Scan (ConstraintAwareAppend) (never executed) + Hypertable: metrics_ordered_idx + Chunks excluded during startup: 2 +(13 rows) --query with no results -- :PREFIX diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index 8887dac8469..45bf3e901f1 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -183,77 +183,74 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; -- Vectorization not possible due to a used filter :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_value > 0; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate Output: sum(_hyper_1_1_chunk.segment_by_value) - -> Gather - Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) - Workers Planned: 2 - -> Parallel Append - -> Custom Scan (VectorAgg) - Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) - Grouping Policy: all compressed batches - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk - Output: _hyper_1_1_chunk.segment_by_value - Vectorized Filter: (_hyper_1_1_chunk.int_value > 0) - -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk - Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value - Filter: (compress_hyper_2_11_chunk.segment_by_value > 0) - -> Custom Scan (VectorAgg) - Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) - Grouping Policy: all compressed batches - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk - Output: _hyper_1_2_chunk.segment_by_value - Vectorized Filter: (_hyper_1_2_chunk.int_value > 0) - -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk - Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value - Filter: (compress_hyper_2_12_chunk.segment_by_value > 0) - -> Custom Scan (VectorAgg) - Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) - Grouping Policy: all compressed batches - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk - Output: _hyper_1_3_chunk.segment_by_value - Vectorized Filter: (_hyper_1_3_chunk.int_value > 0) - -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk - Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value - Filter: (compress_hyper_2_13_chunk.segment_by_value > 0) - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_4_chunk.segment_by_value) - -> Parallel Seq Scan on _timescaledb_internal._hyper_1_4_chunk - Output: _hyper_1_4_chunk.segment_by_value - Filter: ((_hyper_1_4_chunk.segment_by_value > 0) AND (_hyper_1_4_chunk.int_value > 0)) - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_5_chunk.segment_by_value) - -> Parallel Seq Scan on _timescaledb_internal._hyper_1_5_chunk - Output: _hyper_1_5_chunk.segment_by_value - Filter: ((_hyper_1_5_chunk.segment_by_value > 0) AND (_hyper_1_5_chunk.int_value > 0)) - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_6_chunk.segment_by_value) - -> Parallel Seq Scan on _timescaledb_internal._hyper_1_6_chunk - Output: _hyper_1_6_chunk.segment_by_value - Filter: ((_hyper_1_6_chunk.segment_by_value > 0) AND (_hyper_1_6_chunk.int_value > 0)) - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_7_chunk.segment_by_value) - -> Parallel Seq Scan on _timescaledb_internal._hyper_1_7_chunk - Output: _hyper_1_7_chunk.segment_by_value - Filter: ((_hyper_1_7_chunk.segment_by_value > 0) AND (_hyper_1_7_chunk.int_value > 0)) - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_8_chunk.segment_by_value) - -> Parallel Seq Scan on _timescaledb_internal._hyper_1_8_chunk - Output: _hyper_1_8_chunk.segment_by_value - Filter: ((_hyper_1_8_chunk.segment_by_value > 0) AND (_hyper_1_8_chunk.int_value > 0)) - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_9_chunk.segment_by_value) - -> Parallel Seq Scan on _timescaledb_internal._hyper_1_9_chunk - Output: _hyper_1_9_chunk.segment_by_value - Filter: ((_hyper_1_9_chunk.segment_by_value > 0) AND (_hyper_1_9_chunk.int_value > 0)) - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_10_chunk.segment_by_value) - -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk - Output: _hyper_1_10_chunk.segment_by_value - Filter: ((_hyper_1_10_chunk.segment_by_value > 0) AND (_hyper_1_10_chunk.int_value > 0)) -(68 rows) + -> Append + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk.segment_by_value + Vectorized Filter: (_hyper_1_1_chunk.int_value > 0) + -> Index Scan using compress_hyper_2_11_chunk_segment_by_value__ts_meta_min_1___idx on _timescaledb_internal.compress_hyper_2_11_chunk + Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value + Index Cond: (compress_hyper_2_11_chunk.segment_by_value > 0) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk.segment_by_value + Vectorized Filter: (_hyper_1_2_chunk.int_value > 0) + -> Index Scan using compress_hyper_2_12_chunk_segment_by_value__ts_meta_min_1___idx on _timescaledb_internal.compress_hyper_2_12_chunk + Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value + Index Cond: (compress_hyper_2_12_chunk.segment_by_value > 0) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk.segment_by_value + Vectorized Filter: (_hyper_1_3_chunk.int_value > 0) + -> Index Scan using compress_hyper_2_13_chunk_segment_by_value__ts_meta_min_1___idx on _timescaledb_internal.compress_hyper_2_13_chunk + Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value + Index Cond: (compress_hyper_2_13_chunk.segment_by_value > 0) + -> Partial Aggregate + Output: PARTIAL sum(_hyper_1_4_chunk.segment_by_value) + -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk.segment_by_value + Filter: ((_hyper_1_4_chunk.segment_by_value > 0) AND (_hyper_1_4_chunk.int_value > 0)) + -> Partial Aggregate + Output: PARTIAL sum(_hyper_1_5_chunk.segment_by_value) + -> Seq Scan on _timescaledb_internal._hyper_1_5_chunk + Output: _hyper_1_5_chunk.segment_by_value + Filter: ((_hyper_1_5_chunk.segment_by_value > 0) AND (_hyper_1_5_chunk.int_value > 0)) + -> Partial Aggregate + Output: PARTIAL sum(_hyper_1_6_chunk.segment_by_value) + -> Seq Scan on _timescaledb_internal._hyper_1_6_chunk + Output: _hyper_1_6_chunk.segment_by_value + Filter: ((_hyper_1_6_chunk.segment_by_value > 0) AND (_hyper_1_6_chunk.int_value > 0)) + -> Partial Aggregate + Output: PARTIAL sum(_hyper_1_7_chunk.segment_by_value) + -> Seq Scan on _timescaledb_internal._hyper_1_7_chunk + Output: _hyper_1_7_chunk.segment_by_value + Filter: ((_hyper_1_7_chunk.segment_by_value > 0) AND (_hyper_1_7_chunk.int_value > 0)) + -> Partial Aggregate + Output: PARTIAL sum(_hyper_1_8_chunk.segment_by_value) + -> Seq Scan on _timescaledb_internal._hyper_1_8_chunk + Output: _hyper_1_8_chunk.segment_by_value + Filter: ((_hyper_1_8_chunk.segment_by_value > 0) AND (_hyper_1_8_chunk.int_value > 0)) + -> Partial Aggregate + Output: PARTIAL sum(_hyper_1_9_chunk.segment_by_value) + -> Seq Scan on _timescaledb_internal._hyper_1_9_chunk + Output: _hyper_1_9_chunk.segment_by_value + Filter: ((_hyper_1_9_chunk.segment_by_value > 0) AND (_hyper_1_9_chunk.int_value > 0)) + -> Partial Aggregate + Output: PARTIAL sum(_hyper_1_10_chunk.segment_by_value) + -> Seq Scan on _timescaledb_internal._hyper_1_10_chunk + Output: _hyper_1_10_chunk.segment_by_value + Filter: ((_hyper_1_10_chunk.segment_by_value > 0) AND (_hyper_1_10_chunk.int_value > 0)) +(65 rows) :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; diff --git a/tsl/test/shared/expected/transparent_decompress_chunk-15.out b/tsl/test/shared/expected/transparent_decompress_chunk-15.out index bd32d6cb8da..ceb0994b44f 100644 --- a/tsl/test/shared/expected/transparent_decompress_chunk-15.out +++ b/tsl/test/shared/expected/transparent_decompress_chunk-15.out @@ -144,14 +144,12 @@ QUERY PLAN :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id IS NOT NULL ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - -> Parallel Seq Scan on compress_hyper_X_X_chunk - Filter: (device_id IS NOT NULL) -(8 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + -> Seq Scan on compress_hyper_X_X_chunk + Filter: (device_id IS NOT NULL) +(6 rows) :PREFIX SELECT * FROM :TEST_TABLE WHERE device_id IS NULL ORDER BY time, device_id LIMIT 10; QUERY PLAN @@ -189,26 +187,22 @@ QUERY PLAN :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id = v0 ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Filter: (device_id = v0) - -> Parallel Seq Scan on compress_hyper_X_X_chunk -(8 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Filter: (device_id = v0) + -> Seq Scan on compress_hyper_X_X_chunk +(6 rows) :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id < v1 ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Filter: (device_id < v1) - -> Parallel Seq Scan on compress_hyper_X_X_chunk -(8 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Filter: (device_id < v1) + -> Seq Scan on compress_hyper_X_X_chunk +(6 rows) -- test expressions :PREFIX SELECT * FROM :TEST_TABLE WHERE device_id = 1 + 4 / 2 ORDER BY time, device_id LIMIT 10; @@ -224,14 +218,12 @@ QUERY PLAN :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id = length(substring(version(), 1, 3)) ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time" - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Filter: (device_id = length("substring"(version(), 1, 3))) - -> Parallel Seq Scan on compress_hyper_X_X_chunk -(8 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time" + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Filter: (device_id = length("substring"(version(), 1, 3))) + -> Seq Scan on compress_hyper_X_X_chunk +(6 rows) -- test segment meta pushdown -- order by column and const @@ -247,133 +239,111 @@ QUERY PLAN :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time < '2000-01-01 1:00:00+0' ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Vectorized Filter: ("time" < 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) - -> Parallel Seq Scan on compress_hyper_X_X_chunk - Filter: (_ts_meta_min_1 < 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) -(9 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Vectorized Filter: ("time" < 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) + -> Seq Scan on compress_hyper_X_X_chunk + Filter: (_ts_meta_min_1 < 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) +(7 rows) :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time <= '2000-01-01 1:00:00+0' ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Vectorized Filter: ("time" <= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) - -> Parallel Seq Scan on compress_hyper_X_X_chunk - Filter: (_ts_meta_min_1 <= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) -(9 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Vectorized Filter: ("time" <= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) + -> Seq Scan on compress_hyper_X_X_chunk + Filter: (_ts_meta_min_1 <= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) +(7 rows) :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time >= '2000-01-01 1:00:00+0' ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Vectorized Filter: ("time" >= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) - -> Parallel Seq Scan on compress_hyper_X_X_chunk - Filter: (_ts_meta_max_1 >= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) -(9 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Vectorized Filter: ("time" >= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) + -> Seq Scan on compress_hyper_X_X_chunk + Filter: (_ts_meta_max_1 >= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) +(7 rows) :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time > '2000-01-01 1:00:00+0' ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Vectorized Filter: ("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) - -> Parallel Seq Scan on compress_hyper_X_X_chunk - Filter: (_ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) -(9 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Vectorized Filter: ("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) + -> Seq Scan on compress_hyper_X_X_chunk + Filter: (_ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) +(7 rows) :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE '2000-01-01 1:00:00+0' < time ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Vectorized Filter: ("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) - -> Parallel Seq Scan on compress_hyper_X_X_chunk - Filter: (_ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) -(9 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Vectorized Filter: ("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) + -> Seq Scan on compress_hyper_X_X_chunk + Filter: (_ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) +(7 rows) --pushdowns between order by and segment by columns :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE v0 < 1 ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Vectorized Filter: (v0 < 1) - -> Parallel Seq Scan on compress_hyper_X_X_chunk -(8 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Vectorized Filter: (v0 < 1) + -> Seq Scan on compress_hyper_X_X_chunk +(6 rows) :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE v0 < device_id ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Filter: (v0 < device_id) - -> Parallel Seq Scan on compress_hyper_X_X_chunk -(8 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Filter: (v0 < device_id) + -> Seq Scan on compress_hyper_X_X_chunk +(6 rows) :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id < v0 ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Filter: (device_id < v0) - -> Parallel Seq Scan on compress_hyper_X_X_chunk -(8 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Filter: (device_id < v0) + -> Seq Scan on compress_hyper_X_X_chunk +(6 rows) :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE v1 = device_id ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Filter: (v1 = device_id) - -> Parallel Seq Scan on compress_hyper_X_X_chunk -(8 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Filter: (v1 = device_id) + -> Seq Scan on compress_hyper_X_X_chunk +(6 rows) --pushdown between two order by column (not pushed down) :PREFIX SELECT * FROM :TEST_TABLE WHERE v0 = v1 ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit (actual rows=0 loops=1) - -> Gather Merge (actual rows=0 loops=1) - Workers Planned: 2 - Workers Launched: 2 - -> Sort (actual rows=0 loops=2) - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - Worker 0: Sort Method: quicksort - Worker 1: Sort Method: quicksort - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=0 loops=2) - Filter: (v0 = v1) - Rows Removed by Filter: 8995 - -> Parallel Seq Scan on compress_hyper_X_X_chunk (actual rows=10 loops=2) -(12 rows) + -> Sort (actual rows=0 loops=1) + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + Sort Method: quicksort + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=0 loops=1) + Filter: (v0 = v1) + Rows Removed by Filter: 17990 + -> Seq Scan on compress_hyper_X_X_chunk (actual rows=20 loops=1) +(8 rows) --pushdown of quals on order by and segment by cols anded together :PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE time > '2000-01-01 1:00:00+0' AND device_id = 1 ORDER BY time, device_id LIMIT 10; @@ -394,28 +364,24 @@ QUERY PLAN :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time > '2000-01-01 1:00:00+0' OR device_id = 1 ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Filter: (("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) OR (device_id = 1)) - -> Parallel Seq Scan on compress_hyper_X_X_chunk - Filter: ((_ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) OR (device_id = 1)) -(9 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Filter: (("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) OR (device_id = 1)) + -> Seq Scan on compress_hyper_X_X_chunk + Filter: ((_ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) OR (device_id = 1)) +(7 rows) --functions not yet optimized :PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time < now() ORDER BY time, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - Vectorized Filter: ("time" < now()) - -> Parallel Seq Scan on compress_hyper_X_X_chunk -(8 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + Vectorized Filter: ("time" < now()) + -> Seq Scan on compress_hyper_X_X_chunk +(6 rows) -- test sort optimization interaction :PREFIX_NO_VERBOSE SELECT time FROM :TEST_TABLE ORDER BY time DESC LIMIT 10; @@ -430,13 +396,11 @@ QUERY PLAN :PREFIX_NO_VERBOSE SELECT time, device_id FROM :TEST_TABLE ORDER BY time DESC, device_id LIMIT 10; QUERY PLAN Limit - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: _hyper_X_X_chunk."time" DESC, _hyper_X_X_chunk.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk - -> Parallel Seq Scan on compress_hyper_X_X_chunk -(7 rows) + -> Sort + Sort Key: _hyper_X_X_chunk."time" DESC, _hyper_X_X_chunk.device_id + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk + -> Seq Scan on compress_hyper_X_X_chunk +(5 rows) :PREFIX_NO_VERBOSE SELECT time, device_id FROM :TEST_TABLE ORDER BY device_id, time DESC LIMIT 10; QUERY PLAN @@ -680,11 +644,14 @@ QUERY PLAN Sort Key: m1."time", m1.device_id -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk m1 -> Seq Scan on compress_hyper_X_X_chunk - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk m2 - Filter: (m1."time" = "time") - -> Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1 - Index Cond: (device_id = m1.device_id) -(10 rows) + -> Memoize + Cache Key: m1."time", m1.device_id + Cache Mode: logical + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk m2 + Filter: (m1."time" = "time") + -> Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1 + Index Cond: (device_id = m1.device_id) +(13 rows) :PREFIX_NO_VERBOSE SELECT * @@ -698,23 +665,24 @@ FROM :TEST_TABLE m1 LIMIT 10; QUERY PLAN Limit - -> Merge Join - Merge Cond: (m1."time" = m3."time") - -> Nested Loop + -> Nested Loop + -> Gather Merge + Workers Planned: 2 -> Sort Sort Key: m1."time", m1.device_id - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk m1 - -> Seq Scan on compress_hyper_X_X_chunk - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk m2 - Filter: (m1."time" = "time") - -> Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1 - Index Cond: (device_id = m1.device_id) - -> Sort - Sort Key: m3."time" - -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk m3 - -> Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_2 - Filter: (device_id = 3) -(17 rows) + -> Parallel Hash Join + Hash Cond: (m1."time" = m3."time") + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk m1 + -> Parallel Seq Scan on compress_hyper_X_X_chunk + -> Parallel Hash + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk m3 + -> Parallel Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_2 + Filter: (device_id = 3) + -> Custom Scan (DecompressChunk) on _hyper_X_X_chunk m2 + Filter: (m1."time" = "time") + -> Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1 + Index Cond: (device_id = m1.device_id) +(18 rows) RESET min_parallel_table_scan_size; :PREFIX_NO_VERBOSE