Skip to content

Commit

Permalink
Prevent parallel DecompressChunk in queries with LIMIT
Browse files Browse the repository at this point in the history
In queries with LIMIT a parallel plan is quite often less desirable
due to startup cost and changed ordering behaviour.
  • Loading branch information
svenklemm committed May 3, 2024
1 parent 396dd0c commit f6c73ea
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 145 deletions.
2 changes: 1 addition & 1 deletion tsl/src/nodes/decompress_chunk/decompress_chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,7 @@ ts_decompress_chunk_generate_paths(PlannerInfo *root, RelOptInfo *chunk_rel, Hyp
* if it's planned */
compressed_rel->pathlist = NIL;
/* create parallel paths */
if (compressed_rel->consider_parallel)
if (compressed_rel->consider_parallel && root->limit_tuples <= 0)
{
foreach (lc, compressed_rel->partial_pathlist)
{
Expand Down
252 changes: 108 additions & 144 deletions tsl/test/shared/expected/transparent_decompress_chunk-15.out
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,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
Expand Down Expand Up @@ -187,26 +185,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;
Expand All @@ -222,14 +216,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
Expand All @@ -245,133 +237,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;
Expand All @@ -393,27 +363,23 @@ 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
(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: (("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
(6 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;
Expand All @@ -428,13 +394,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
Expand Down

0 comments on commit f6c73ea

Please sign in to comment.