Re: Hybrid Hash/Nested Loop joins and caching results from subplans
Robert Haas <robertmhaas@gmail.com>
From: Robert Haas <robertmhaas@gmail.com>
To: Alvaro Herrera <alvherre@2ndquadrant.com>
Cc: David Rowley <dgrowleyml@gmail.com>, PostgreSQL Developers <pgsql-hackers@lists.postgresql.org>,
Andres Freund <andres@anarazel.de>
Date: 2020-08-28T15:33:14Z
Lists: pgsql-hackers
On Wed, Aug 19, 2020 at 6:58 PM Alvaro Herrera <alvherre@2ndquadrant.com> wrote: > On 2020-Aug-19, David Rowley wrote: > > Andres' suggestion: > > regression=# explain (analyze, costs off, timing off, summary off) > > select count(*) from tenk1 t1 inner join tenk1 t2 on > > t1.twenty=t2.unique1; > > QUERY PLAN > > --------------------------------------------------------------------------------------- > > Aggregate (actual rows=1 loops=1) > > -> Nested Loop (actual rows=10000 loops=1) > > Cache Key: t1.twenty Hits: 9980 Misses: 20 Evictions: 0 Overflows: 0 > > -> Seq Scan on tenk1 t1 (actual rows=10000 loops=1) > > -> Index Scan using tenk1_unique1 on tenk1 t2 (actual rows=1 loops=20) > > Index Cond: (unique1 = t1.twenty) > > (6 rows) > > I think it doesn't look terrible in the SubPlan case -- it kinda makes > sense there -- but for nested loop it appears really strange. I disagree. I don't know why anyone should find this confusing, except that we're not used to seeing it. It seems to make a lot of sense that if you are executing the same plan tree with different parameters, you might want to cache results to avoid recomputation. So why wouldn't nodes that do this include a cache? This is not necessarily a vote for Andres's proposal. I don't know whether it's technically better to include the caching in the Nested Loop node or to make it a separate node, and I think we should do the one that's better. Getting pushed into an inferior design because we think the EXPLAIN output will be clearer does not make sense to me. I think David's points elsewhere on the thread about ProjectSet and Materialize nodes are interesting. It was never very clear to me why ProjectSet was handled separately in every node, adding quite a bit of complexity, and why Materialize was a separate node. Likewise, why are Hash Join and Hash two separate nodes instead of just one? Why do we not treat projection as a separate node type even when we're not projecting a set? In general, I've never really understood why we choose to include some functionality in other nodes and keep other things separate. Is there even an organizing principle, or is it just historical baggage? -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company
Commits
-
Add Result Cache executor node (take 2)
- 9eacee2e62d8 14.0 landed
-
Add Result Cache executor node
- b6002a796dc0 14.0 landed
-
Allow estimate_num_groups() to pass back further details about the estimation
- ed934d4fa30f 14.0 landed
-
Allow users of simplehash.h to perform direct deletions
- ff53d7b159b9 14.0 landed
-
Cache if PathTarget and RestrictInfos contain volatile functions
- f58b230ed0db 14.0 landed
-
Fix pull_varnos' miscomputation of relids set for a PlaceHolderVar.
- 55dc86eca70b 14.0 cited