mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
Further fallout from the MergeAppend patch.
Fix things so that top-N sorting can be used in child Sort nodes of a MergeAppend node, when there is a LIMIT and no intervening joins or grouping. Actually doing this on the executor side isn't too bad, but it's a bit messier to get the planner to cost it properly. Per gripe from Robert Haas. In passing, fix an oversight in the original top-N-sorting patch: query_planner should not assume that a LIMIT can be used to make an explicit sort cheaper when there will be grouping or aggregation in between. Possibly this should be back-patched, but I'm not sure the mistake is serious enough to be a real problem in practice.
This commit is contained in:
@ -25,6 +25,7 @@
|
||||
#include "executor/nodeLimit.h"
|
||||
|
||||
static void recompute_limits(LimitState *node);
|
||||
static void pass_down_bound(LimitState *node, PlanState *child_node);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@ -293,26 +294,35 @@ recompute_limits(LimitState *node)
|
||||
/* Set state-machine state */
|
||||
node->lstate = LIMIT_RESCAN;
|
||||
|
||||
/*
|
||||
* If we have a COUNT, and our input is a Sort node, notify it that it can
|
||||
* use bounded sort.
|
||||
*
|
||||
* This is a bit of a kluge, but we don't have any more-abstract way of
|
||||
* communicating between the two nodes; and it doesn't seem worth trying
|
||||
* to invent one without some more examples of special communication
|
||||
* needs.
|
||||
*
|
||||
* Note: it is the responsibility of nodeSort.c to react properly to
|
||||
* changes of these parameters. If we ever do redesign this, it'd be a
|
||||
* good idea to integrate this signaling with the parameter-change
|
||||
* mechanism.
|
||||
*/
|
||||
if (IsA(outerPlanState(node), SortState))
|
||||
/* Notify child node about limit, if useful */
|
||||
pass_down_bound(node, outerPlanState(node));
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a COUNT, and our input is a Sort node, notify it that it can
|
||||
* use bounded sort. Also, if our input is a MergeAppend, we can apply the
|
||||
* same bound to any Sorts that are direct children of the MergeAppend,
|
||||
* since the MergeAppend surely need read no more than that many tuples from
|
||||
* any one input. We also have to be prepared to look through a Result,
|
||||
* since the planner might stick one atop MergeAppend for projection purposes.
|
||||
*
|
||||
* This is a bit of a kluge, but we don't have any more-abstract way of
|
||||
* communicating between the two nodes; and it doesn't seem worth trying
|
||||
* to invent one without some more examples of special communication needs.
|
||||
*
|
||||
* Note: it is the responsibility of nodeSort.c to react properly to
|
||||
* changes of these parameters. If we ever do redesign this, it'd be a
|
||||
* good idea to integrate this signaling with the parameter-change mechanism.
|
||||
*/
|
||||
static void
|
||||
pass_down_bound(LimitState *node, PlanState *child_node)
|
||||
{
|
||||
if (IsA(child_node, SortState))
|
||||
{
|
||||
SortState *sortState = (SortState *) outerPlanState(node);
|
||||
SortState *sortState = (SortState *) child_node;
|
||||
int64 tuples_needed = node->count + node->offset;
|
||||
|
||||
/* negative test checks for overflow */
|
||||
/* negative test checks for overflow in sum */
|
||||
if (node->noCount || tuples_needed < 0)
|
||||
{
|
||||
/* make sure flag gets reset if needed upon rescan */
|
||||
@ -324,6 +334,19 @@ recompute_limits(LimitState *node)
|
||||
sortState->bound = tuples_needed;
|
||||
}
|
||||
}
|
||||
else if (IsA(child_node, MergeAppendState))
|
||||
{
|
||||
MergeAppendState *maState = (MergeAppendState *) child_node;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < maState->ms_nplans; i++)
|
||||
pass_down_bound(node, maState->mergeplans[i]);
|
||||
}
|
||||
else if (IsA(child_node, ResultState))
|
||||
{
|
||||
if (outerPlanState(child_node))
|
||||
pass_down_bound(node, outerPlanState(child_node));
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user