Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9d9c02c

Browse files
committed
Teach planner and executor about monotonic window funcs
Window functions such as row_number() always return a value higher thanthe previously returned value for tuples in any given window partition.Traditionally queries such as;SELECT * FROM ( SELECT *, row_number() over (order by c) rn FROM t) t WHERE rn <= 10;were executed fairly inefficiently. Neither the query planner nor theexecutor knew that once rn made it to 11 that nothing further would matchthe outer query's WHERE clause. It would blindly continue until alltuples were exhausted from the subquery.Here we implement means to make the above execute more efficiently.This is done by way of adding a pg_proc.prosupport function to various ofthe built-in window functions and adding supporting code to allow thesupport function to inform the planner if the window function ismonotonically increasing, monotonically decreasing, both or neither. Theplanner is then able to make use of that information and possibly allowthe executor to short-circuit execution by way of adding a "run condition"to the WindowAgg to allow it to determine if some of its execution workcan be skipped.This "run condition" is not like a normal filter. These run conditionsare only built using quals comparing values to monotonic window functions.For monotonic increasing functions, quals making use of the btreeoperators for <, <= and = can be used (assuming the window function columnis on the left). You can see here that once such a condition becomes falsethat a monotonic increasing function could never make it subsequently trueagain. For monotonically decreasing functions the >, >= and = btreeoperators for the given type can be used for run conditions.The best-case situation for this is when there is a single WindowAgg nodewithout a PARTITION BY clause. Here when the run condition becomes falsethe WindowAgg node can simply return NULL. No more tuples will ever matchthe run condition. It's a little more complex when there is a PARTITIONBY clause. In this case, we cannot return NULL as we must still processother partitions. To speed this case up we pull tuples from the outerplan to check if they're from the same partition and simply discard themif they are. When we find a tuple belonging to another partition we startprocessing as normal again until the run condition becomes false or we runout of tuples to process.When there are multiple WindowAgg nodes to evaluate then this complicatesthe situation. For intermediate WindowAggs we must ensure we alwaysreturn all tuples to the calling node. Any filtering done could lead toincorrect results in WindowAgg nodes above. For all intermediate nodes,we can still save some work when the run condition becomes false. We'veno need to evaluate the WindowFuncs anymore. Other WindowAgg nodes cannotreference the value of these and these tuples will not appear in the finalresult anyway. The savings here are small in comparison to what can besaved in the top-level WingowAgg, but still worthwhile.Intermediate WindowAgg nodes never filter out tuples, but here we changeWindowAgg so that the top-level WindowAgg filters out tuples that don'tmatch the intermediate WindowAgg node's run condition. Such filtersappear in the "Filter" clause in EXPLAIN for the top-level WindowAgg node.Here we add prosupport functions to allow the above to work for;row_number(), rank(), dense_rank(), count(*) and count(expr). It appearstechnically possible to do the same for min() and max(), however, it seemsunlikely to be useful enough, so that's not done here.Bump catversionAuthor: David RowleyReviewed-by: Andy Fan, Zhihong YuDiscussion:https://postgr.es/m/CAApHDvqvp3At8++yF8ij06sdcoo1S_b2YoaT9D4Nf+MObzsrLQ@mail.gmail.com
1 parent2f4d0d6 commit9d9c02c

File tree

24 files changed

+1547
-151
lines changed

24 files changed

+1547
-151
lines changed

‎src/backend/commands/explain.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,6 +1988,14 @@ ExplainNode(PlanState *planstate, List *ancestors,
19881988
show_instrumentation_count("Rows Removed by Filter",1,
19891989
planstate,es);
19901990
break;
1991+
caseT_WindowAgg:
1992+
show_upper_qual(plan->qual,"Filter",planstate,ancestors,es);
1993+
if (plan->qual)
1994+
show_instrumentation_count("Rows Removed by Filter",1,
1995+
planstate,es);
1996+
show_upper_qual(((WindowAgg*)plan)->runConditionOrig,
1997+
"Run Condition",planstate,ancestors,es);
1998+
break;
19911999
caseT_Group:
19922000
show_group_keys(castNode(GroupState,planstate),ancestors,es);
19932001
show_upper_qual(plan->qual,"Filter",planstate,ancestors,es);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp