postgres.git / summary / log / commit / refs

commit    0ff865fbe50e82f17df8a9280fa01faf270b7f3f
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Fri Feb 05 04:01:33 2021 +0000
First released in: 14.0, 13.2

    Fix bug in HashAgg's selective-column-spilling logic.
    
    Commit 230230223 taught nodeAgg.c that, when spilling tuples from
    memory in an oversized hash aggregation, it only needed to spill
    input columns referenced in the node's tlist and quals.  Unfortunately,
    that's wrong: we also have to save the grouping columns.  The error
    is masked in common cases because the grouping columns also appear
    in the tlist, but that's not necessarily true.  The main category
    of plans where it's not true seem to come from semijoins ("WHERE
    outercol IN (SELECT innercol FROM innertable)") where the innercol
    needs an implicit promotion to make it comparable to the outercol.
    The grouping column will be "innercol::promotedtype", but that
    expression appears nowhere in the Agg node's own tlist and quals;
    only the bare "innercol" is found in the tlist.
    
    I spent quite a bit of time looking for a suitable regression test
    case for this, without much success.  If the number of distinct
    values of the innercol is large enough to make spilling happen,
    the planner tends to prefer a non-HashAgg plan, at least for
    problem sizes that are reasonable to use in the regression tests.
    So, no new regression test.  However, this patch does demonstrably
    fix the originally-reported test case.
    
    Per report from s.p.e (at) gmx-topmail.de.  Backpatch to v13
    where the troublesome code came in.
    
    Discussion: https://postgr.es/m/trinity-1c565d44-159f-488b-a518-caf13883134f-1611835701633@3c-app-gmx-bap78


src/backend/executor/nodeAgg.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 601b6dab03f..1d1bf958b62 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -1391,7 +1391,7 @@ project_aggregates(AggState *aggstate) } /* - * Walk tlist and qual to find referenced colnos, dividing them into + * Find input-tuple columns that are needed, dividing them into * aggregated and unaggregated sets. */ static void @@ -1404,9 +1404,15 @@ find_cols(AggState *aggstate, Bitmapset **aggregated, Bitmapset **unaggregated) context.aggregated = NULL; context.unaggregated = NULL; + /* Examine tlist and quals */ (void) find_cols_walker((Node *) agg->plan.targetlist, &context); (void) find_cols_walker((Node *) agg->plan.qual, &context); + /* In some cases, grouping columns will not appear in the tlist */ + for (int i = 0; i < agg->numCols; i++) + context.unaggregated = bms_add_member(context.unaggregated, + agg->grpColIdx[i]); + *aggregated = context.aggregated; *unaggregated = context.unaggregated; } [parent: e1c02d92aee3]