1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-14 18:42:34 +03:00

Reduce the cost of planning deeply-nested views.

Joel Jacobson reported that deep nesting of trivial (flattenable)
views results in O(N^3) growth of planning time for N-deep nesting.
It turns out that a large chunk of this cost comes from copying around
the "subquery" sub-tree of each view's RTE_SUBQUERY RTE.  But once we
have successfully flattened the subquery, we don't need that anymore,
because the planner isn't going to do anything else interesting with
that RTE.  We already zap the subquery pointer during setrefs.c (cf.
add_rte_to_flat_rtable), but it's useless baggage earlier than that
too.  Clearing the pointer as soon as pull_up_simple_subquery is done
with the RTE reduces the cost from O(N^3) to O(N^2); which is still
not great, but it's quite a lot better.  Further improvements will
require rethinking of the RTE data structure, which is being considered
in another thread.

Patch by me; thanks to Dean Rasheed for review.

Discussion: https://postgr.es/m/797aff54-b49b-4914-9ff9-aa42564a4d7d@www.fastmail.com
This commit is contained in:
Tom Lane
2021-07-06 14:23:09 -04:00
parent c7b7311f61
commit 64919aaab4

View File

@ -893,10 +893,9 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
ListCell *lc; ListCell *lc;
/* /*
* Need a modifiable copy of the subquery to hack on. Even if we didn't * Make a modifiable copy of the subquery to hack on, so that the RTE will
* sometimes choose not to pull up below, we must do this to avoid * be left unchanged in case we decide below that we can't pull it up
* problems if the same subquery is referenced from multiple jointree * after all.
* items (which can't happen normally, but might after rule rewriting).
*/ */
subquery = copyObject(rte->subquery); subquery = copyObject(rte->subquery);
@ -1174,6 +1173,14 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
Assert(root->placeholder_list == NIL); Assert(root->placeholder_list == NIL);
Assert(subroot->placeholder_list == NIL); Assert(subroot->placeholder_list == NIL);
/*
* We no longer need the RTE's copy of the subquery's query tree. Getting
* rid of it saves nothing in particular so far as this level of query is
* concerned; but if this query level is in turn pulled up into a parent,
* we'd waste cycles copying the now-unused query tree.
*/
rte->subquery = NULL;
/* /*
* Miscellaneous housekeeping. * Miscellaneous housekeeping.
* *