Re: Early WIP/PoC for inlining CTEs
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: Andrew Gierth <andrew@tao11.riddles.org.uk>
Cc: Andreas Karlsson <andreas@proxel.se>,
Tomas Vondra <tomas.vondra@2ndquadrant.com>,
Merlin Moncure <mmoncure@gmail.com>,
Alvaro Herrera <alvherre@2ndquadrant.com>,
Peter Eisentraut <peter.eisentraut@2ndquadrant.com>,
Michael Paquier <michael@paquier.xyz>,
Robert Haas <robertmhaas@gmail.com>,
Andres Freund <andres@anarazel.de>,
Thomas Munro <thomas.munro@enterprisedb.com>,
David Fetter <david@fetter.org>,
Pg Hackers <pgsql-hackers@postgresql.org>
Date: 2019-02-26T14:51:38Z
Lists: pgsql-hackers
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Prevent inlining of multiply-referenced CTEs with outer recursive refs.
- 9476131278c7 12.0 landed
-
Allow user control of CTE materialization, and change the default behavior.
- 608b167f9f9c 12.0 landed
-
Split QTW_EXAMINE_RTES flag into QTW_EXAMINE_RTES_BEFORE/_AFTER.
- 18c0da88a5d9 12.0 landed
-
document when PREPARE uses generic plans
- fab9d1da4a21 9.6.0 cited
Andrew Gierth <andrew@tao11.riddles.org.uk> writes:
> Here, uncommenting that NOT actually changes the result, from 22 rows to
> 4 rows, because we end up generating multiple worktable scans and the
> recursion logic is not set up to handle that.
Ugh.
> So what I think we need to do here is to forbid inlining if (a) the
> refcount is greater than 1 and (b) the CTE in question contains,
> recursively anywhere inside its rtable or the rtables of any of its
> nested CTEs, a "self_reference" RTE.
That's kind of "ugh" too: it sounds expensive, and doing it in a way
that doesn't produce false positives would be even more complicated.
Idle uncaffeinated speculation: is it practical to fix the restriction
about multiple worktable scans?
Also, I thought of a somewhat-related scenario that the code isn't
accounting for: you can break the restrictions about single evaluation
with nested WITHs, like
with x as not materialized (with y as materialized (select random() r) select * from y)
select * from x, x x1;
In this particular example, we're saved from computing random() twice
by the checks for volatile functions. But without that, y is inlined
and computed twice, e.g.
explain verbose with x as not materialized (with y as (select now() r) select * from y)
select * from x, x x1;
QUERY PLAN
------------------------------------------------
Nested Loop (cost=0.00..0.06 rows=1 width=16)
Output: (now()), (now())
-> Result (cost=0.00..0.01 rows=1 width=8)
Output: now()
-> Result (cost=0.00..0.01 rows=1 width=8)
Output: now()
(6 rows)
As a user I think I'd find that surprising, and bad if y were expensive.
Is it practical to inline the outer "x" level and still compute "y"
only once? If not, I think we need to disallow inlining anything
that contains a "with".
regards, tom lane