Skip to content

Commit

Permalink
Don't add unneded null test in sorted query plan for minmax
Browse files Browse the repository at this point in the history
If we use NULLS LAST, we don't need the null test. This saves some CPU.
  • Loading branch information
akuzm committed Jan 10, 2024
1 parent d940831 commit 9c75b03
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 165 deletions.
28 changes: 17 additions & 11 deletions src/planner/agg_bookend.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,17 +629,23 @@ build_first_last_path(PlannerInfo *root, FirstLastAggInfo *fl_info, Oid eqop, Oi
parse->hasDistinctOn = false;
parse->hasAggs = false;

/* Build "sort IS NOT NULL" expression. Not that target can still be NULL */
ntest = makeNode(NullTest);
ntest->nulltesttype = IS_NOT_NULL;
ntest->arg = copyObject(fl_info->sort);
/* we checked it wasn't a rowtype in find_minmax_aggs_walker */
ntest->argisrow = false;
ntest->location = -1;

/* User might have had that in WHERE already */
if (!list_member((List *) parse->jointree->quals, ntest))
parse->jointree->quals = (Node *) lcons(ntest, (List *) parse->jointree->quals);
/*
* Build "sort IS NOT NULL" expression. Note that target can still be NULL.
* We don't need it if the order is NULLS LAST.
*/
if (nulls_first)
{
ntest = makeNode(NullTest);
ntest->nulltesttype = IS_NOT_NULL;
ntest->arg = copyObject(fl_info->sort);
/* we checked it wasn't a rowtype in find_minmax_aggs_walker */
ntest->argisrow = false;
ntest->location = -1;

/* User might have had that in WHERE already */
if (!list_member((List *) parse->jointree->quals, ntest))
parse->jointree->quals = (Node *) lcons(ntest, (List *) parse->jointree->quals);
}

/* Build suitable ORDER BY clause */
sortcl = makeNode(SortGroupClause);
Expand Down
47 changes: 13 additions & 34 deletions test/expected/agg_bookends.out
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ SELECT setting, current_setting(setting) AS value from (VALUES ('timescaledb.ena
InitPlan 1 (returns $0)
-> Limit (actual rows=1 loops=1)
-> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (actual rows=1 loops=1)
Index Cond: ("time" IS NOT NULL)
(5 rows)
(4 rows)

:PREFIX SELECT last(temp, time_alt) FROM btest;
QUERY PLAN
Expand Down Expand Up @@ -398,16 +397,11 @@ INSERT INTO btest_numeric VALUES('2020-01-20T09:00:43', 30.5);
-> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1)
Order: btest."time"
-> Index Scan Backward using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (actual rows=1 loops=1)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (never executed)
Index Cond: ("time" IS NOT NULL)
(15 rows)
(10 rows)

-- can't do index scan when ordering on non-index column
:PREFIX SELECT first(temp, time_alt) FROM btest;
Expand Down Expand Up @@ -517,16 +511,11 @@ INSERT INTO btest_numeric VALUES('2020-01-20T09:00:43', 30.5);
-> Custom Scan (ChunkAppend) on btest btest_1 (actual rows=1 loops=1)
Order: btest_1."time"
-> Index Scan Backward using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk _hyper_1_4_chunk_1 (actual rows=1 loops=1)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk _hyper_1_1_chunk_1 (never executed)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk _hyper_1_2_chunk_1 (never executed)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk _hyper_1_3_chunk_1 (never executed)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk _hyper_1_5_chunk_1 (never executed)
Index Cond: ("time" IS NOT NULL)
(29 rows)
(24 rows)

-- verify results when using both FIRST and LAST
:PREFIX SELECT first(temp, time), last(temp, time) FROM btest;
Expand All @@ -552,16 +541,11 @@ INSERT INTO btest_numeric VALUES('2020-01-20T09:00:43', 30.5);
-> Custom Scan (ChunkAppend) on btest btest_1 (actual rows=1 loops=1)
Order: btest_1."time"
-> Index Scan Backward using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk _hyper_1_4_chunk_1 (actual rows=1 loops=1)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk _hyper_1_1_chunk_1 (never executed)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk _hyper_1_2_chunk_1 (never executed)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk _hyper_1_3_chunk_1 (never executed)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk _hyper_1_5_chunk_1 (never executed)
Index Cond: ("time" IS NOT NULL)
(29 rows)
(24 rows)

-- do index scan when using WHERE
:PREFIX SELECT last(temp, time) FROM btest WHERE time <= '2017-01-20T09:00:02';
Expand Down Expand Up @@ -661,21 +645,21 @@ INSERT INTO btest_numeric VALUES('2020-01-20T09:00:43', 30.5);
-- SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47';
-- do index scan
:PREFIX SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Result (actual rows=1 loops=1)
InitPlan 1 (returns $0)
-> Limit (actual rows=1 loops=1)
-> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1)
Order: btest."time"
-> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (actual rows=1 loops=1)
Index Cond: (("time" IS NOT NULL) AND ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone))
Index Cond: ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone)
-> Index Scan Backward using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed)
Index Cond: (("time" IS NOT NULL) AND ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone))
Index Cond: ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone)
-> Index Scan Backward using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed)
Index Cond: (("time" IS NOT NULL) AND ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone))
Index Cond: ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone)
-> Index Scan Backward using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (never executed)
Index Cond: (("time" IS NOT NULL) AND ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone))
Index Cond: ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone)
(13 rows)

-- can't do index scan when using WINDOW function
Expand Down Expand Up @@ -811,8 +795,7 @@ INSERT INTO btest_numeric VALUES('2018-01-20T09:00:43', NULL);
InitPlan 1 (returns $0)
-> Limit (actual rows=1 loops=1)
-> Index Scan Backward using _hyper_2_8_chunk_btest_numeric_time_idx on _hyper_2_8_chunk (actual rows=1 loops=1)
Index Cond: ("time" IS NOT NULL)
(5 rows)
(4 rows)

:PREFIX SELECT last(quantity, time) FROM btest_numeric;
QUERY PLAN
Expand Down Expand Up @@ -850,10 +833,8 @@ INSERT INTO btest_numeric VALUES('2019-01-20T09:00:43', 2);
-> Custom Scan (ChunkAppend) on btest_numeric (actual rows=1 loops=1)
Order: btest_numeric."time"
-> Index Scan Backward using _hyper_2_8_chunk_btest_numeric_time_idx on _hyper_2_8_chunk (actual rows=1 loops=1)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_2_9_chunk_btest_numeric_time_idx on _hyper_2_9_chunk (never executed)
Index Cond: ("time" IS NOT NULL)
(9 rows)
(7 rows)

:PREFIX SELECT last(quantity, time) FROM btest_numeric;
QUERY PLAN
Expand Down Expand Up @@ -912,10 +893,8 @@ INSERT INTO btest_numeric VALUES('2018-01-20T09:00:43', NULL);
-> Custom Scan (ChunkAppend) on btest_numeric (actual rows=1 loops=1)
Order: btest_numeric."time"
-> Index Scan Backward using _hyper_2_11_chunk_btest_numeric_time_idx on _hyper_2_11_chunk (actual rows=1 loops=1)
Index Cond: ("time" IS NOT NULL)
-> Index Scan Backward using _hyper_2_10_chunk_btest_numeric_time_idx on _hyper_2_10_chunk (never executed)
Index Cond: ("time" IS NOT NULL)
(9 rows)
(7 rows)

:PREFIX SELECT last(quantity, time) FROM btest_numeric;
QUERY PLAN
Expand Down
3 changes: 1 addition & 2 deletions test/expected/plan_expand_hypertable-13.out
Original file line number Diff line number Diff line change
Expand Up @@ -2828,8 +2828,7 @@ SET enable_seqscan=false;
InitPlan 1 (returns $0)
-> Limit
-> Index Scan Backward using _hyper_1_1_chunk_hyper_time_idx on _hyper_1_1_chunk h
Index Cond: ("time" IS NOT NULL)
(5 rows)
(4 rows)

\set ON_ERROR_STOP 0
SELECT * FROM hyper WHERE _timescaledb_functions.chunks_in(hyper, ARRAY[1,2]) AND _timescaledb_functions.chunks_in(hyper, ARRAY[2,3]);
Expand Down
3 changes: 1 addition & 2 deletions test/expected/plan_expand_hypertable-14.out
Original file line number Diff line number Diff line change
Expand Up @@ -2828,8 +2828,7 @@ SET enable_seqscan=false;
InitPlan 1 (returns $0)
-> Limit
-> Index Scan Backward using _hyper_1_1_chunk_hyper_time_idx on _hyper_1_1_chunk h
Index Cond: ("time" IS NOT NULL)
(5 rows)
(4 rows)

\set ON_ERROR_STOP 0
SELECT * FROM hyper WHERE _timescaledb_functions.chunks_in(hyper, ARRAY[1,2]) AND _timescaledb_functions.chunks_in(hyper, ARRAY[2,3]);
Expand Down
3 changes: 1 addition & 2 deletions test/expected/plan_expand_hypertable-15.out
Original file line number Diff line number Diff line change
Expand Up @@ -2828,8 +2828,7 @@ SET enable_seqscan=false;
InitPlan 1 (returns $0)
-> Limit
-> Index Scan Backward using _hyper_1_1_chunk_hyper_time_idx on _hyper_1_1_chunk h
Index Cond: ("time" IS NOT NULL)
(5 rows)
(4 rows)

\set ON_ERROR_STOP 0
SELECT * FROM hyper WHERE _timescaledb_functions.chunks_in(hyper, ARRAY[1,2]) AND _timescaledb_functions.chunks_in(hyper, ARRAY[2,3]);
Expand Down
3 changes: 1 addition & 2 deletions test/expected/plan_expand_hypertable-16.out
Original file line number Diff line number Diff line change
Expand Up @@ -2826,8 +2826,7 @@ SET enable_seqscan=false;
InitPlan 1 (returns $0)
-> Limit
-> Index Scan Backward using _hyper_1_1_chunk_hyper_time_idx on _hyper_1_1_chunk h
Index Cond: ("time" IS NOT NULL)
(5 rows)
(4 rows)

\set ON_ERROR_STOP 0
SELECT * FROM hyper WHERE _timescaledb_functions.chunks_in(hyper, ARRAY[1,2]) AND _timescaledb_functions.chunks_in(hyper, ARRAY[2,3]);
Expand Down
Loading

0 comments on commit 9c75b03

Please sign in to comment.