Em qua., 15 de set. de 2021 às 15:35, Tom Lane <t...@sss.pgh.pa.us> escreveu:

> Ranier Vilela <ranier...@gmail.com> writes:
> > Em qua., 15 de set. de 2021 às 12:00, Tom Lane <t...@sss.pgh.pa.us>
> escreveu:
> >> We could, in fact, not bother with removing the no-longer-referenced
> >> subplans, and it probably wouldn't be all that awful.  But the intent
> >> of the original patch was to save the executor startup time for such
> >> subplans, so I wanted to preserve that goal if I could.
>
> > I'm sorry if I'm being persistent with this issue, but I'd like to give
> it
> > one last try before I let it go
> > I modified the way the subplane deletion is done and it seems to me that
> > this really happens.
>
> It looks like what this fragment is doing is clobbering the List
> substructure of the AlternativeSubPlan node itself.  That's not
> going to make any difference, since the whole point of the exercise
> is that the AlternativeSubPlan gets cut out of the finished tree.
> But the list that we want to modify, in order to save the
> executor time, is the root->glob->subplans list (which ends
> up being PlannedStmt.subplans).  And that's global to the
> query, so we can't fix it correctly on the basis of a single
> AlternativeSubPlan.
>
Ok, I can see now.
But this leads me to the conclusion that AlternativeSubPlan *asplan
does not seem to me to be a good approach for this function, better to deal
with it directly:
"root->glob->subplans" which, it seems, works too.

i = 0;
foreach(lc, root->glob->subplans)
{
      SubPlan    *curplan = (SubPlan *) lfirst(lc);
      Cost curcost;

      curcost = curplan->startup_cost + num_exec * curplan->per_call_cost;
      if (bestplan == NULL || curcost <= bestcost)
      {
           bestplan = curplan;
           bestcost = curcost;
      }
      i++;
}

if (bestplan != NULL)
{
       foreach(lc, root->glob->subplans)
       {
            SubPlan    *curplan = (SubPlan *) lfirst(lc);
            if (curplan != bestplan)
                lfirst(lc) = NULL;
       }
       j = 0;
      foreach(lc, root->glob->subplans)
      {
            SubPlan    *curplan = (SubPlan *) lfirst(lc);
            if (curplan != NULL)
                j++;
      }
      if (j != i)
      {
            ereport(ERROR,
            (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                errmsg("too many subplans: total_plans=%d,
remain_plans=%d", i, j)));
       }
}

postgres=# explain (costs off)
postgres-# select * from exists_tbl t1
postgres-#   where (exists(select 1 from exists_tbl t2 where t1.c1 = t2.c2)
or c3 < 0);
ERROR:  too many subplans: total_plans=2, remain_plans=1
postgres=# select * from exists_tbl t1
postgres-#   where (exists(select 1 from exists_tbl t2 where t1.c1 = t2.c2)
or c3 < 0);
ERROR:  too many subplans: total_plans=2, remain_plans=1

Anyway, thank you for the explanations.

regards,
Ranier Vilela

Reply via email to