mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-11 19:20:40 +08:00
Fix Memoize to work with partitionwise joining.
A couple of places weren't up to speed for this. By sheer good luck, we didn't fail but just selected a non-memoized join plan, at least in the test case we have. Nonetheless, it's a bug, and I'm not quite sure that it couldn't have worse consequences in other examples. So back-patch to v14 where Memoize came in. Richard Guo Discussion: https://postgr.es/m/CAMbWs48GkNom272sfp0-WeD6_0HSR19BJ4H1c9ZKSfbVnJsvRg@mail.gmail.com
This commit is contained in:
parent
35ce24c333
commit
d69d01ba9d
@ -597,7 +597,8 @@ get_memoize_path(PlannerInfo *root, RelOptInfo *innerrel,
|
||||
/* Check if we have hash ops for each parameter to the path */
|
||||
if (paraminfo_get_equal_hashops(root,
|
||||
inner_path->param_info,
|
||||
outerrel,
|
||||
outerrel->top_parent ?
|
||||
outerrel->top_parent : outerrel,
|
||||
innerrel,
|
||||
¶m_exprs,
|
||||
&hash_operators,
|
||||
|
@ -4246,6 +4246,7 @@ do { \
|
||||
|
||||
FLAT_COPY_PATH(mpath, path, MemoizePath);
|
||||
REPARAMETERIZE_CHILD_PATH(mpath->subpath);
|
||||
ADJUST_CHILD_ATTRS(mpath->param_exprs);
|
||||
new_path = (Path *) mpath;
|
||||
}
|
||||
break;
|
||||
|
@ -1865,8 +1865,8 @@ typedef struct MemoizePath
|
||||
{
|
||||
Path path;
|
||||
Path *subpath; /* outerpath to cache tuples from */
|
||||
List *hash_operators; /* hash operators for each key */
|
||||
List *param_exprs; /* cache keys */
|
||||
List *hash_operators; /* OIDs of hash equality ops for cache keys */
|
||||
List *param_exprs; /* expressions that are cache keys */
|
||||
bool singlerow; /* true if the cache entry is to be marked as
|
||||
* complete after caching the first record. */
|
||||
bool binary_mode; /* true when cache key should be compared bit
|
||||
|
@ -197,6 +197,45 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false);
|
||||
(8 rows)
|
||||
|
||||
DROP TABLE strtest;
|
||||
-- Ensure memoize works with partitionwise join
|
||||
SET enable_partitionwise_join TO on;
|
||||
CREATE TABLE prt (a int) PARTITION BY RANGE(a);
|
||||
CREATE TABLE prt_p1 PARTITION OF prt FOR VALUES FROM (0) TO (10);
|
||||
CREATE TABLE prt_p2 PARTITION OF prt FOR VALUES FROM (10) TO (20);
|
||||
INSERT INTO prt VALUES (0), (0), (0), (0);
|
||||
INSERT INTO prt VALUES (10), (10), (10), (10);
|
||||
CREATE INDEX iprt_p1_a ON prt_p1 (a);
|
||||
CREATE INDEX iprt_p2_a ON prt_p2 (a);
|
||||
ANALYZE prt;
|
||||
SELECT explain_memoize('
|
||||
SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false);
|
||||
explain_memoize
|
||||
------------------------------------------------------------------------------------------
|
||||
Append (actual rows=32 loops=N)
|
||||
-> Nested Loop (actual rows=16 loops=N)
|
||||
-> Index Only Scan using iprt_p1_a on prt_p1 t1_1 (actual rows=4 loops=N)
|
||||
Heap Fetches: N
|
||||
-> Memoize (actual rows=4 loops=N)
|
||||
Cache Key: t1_1.a
|
||||
Cache Mode: logical
|
||||
Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB
|
||||
-> Index Only Scan using iprt_p1_a on prt_p1 t2_1 (actual rows=4 loops=N)
|
||||
Index Cond: (a = t1_1.a)
|
||||
Heap Fetches: N
|
||||
-> Nested Loop (actual rows=16 loops=N)
|
||||
-> Index Only Scan using iprt_p2_a on prt_p2 t1_2 (actual rows=4 loops=N)
|
||||
Heap Fetches: N
|
||||
-> Memoize (actual rows=4 loops=N)
|
||||
Cache Key: t1_2.a
|
||||
Cache Mode: logical
|
||||
Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB
|
||||
-> Index Only Scan using iprt_p2_a on prt_p2 t2_2 (actual rows=4 loops=N)
|
||||
Index Cond: (a = t1_2.a)
|
||||
Heap Fetches: N
|
||||
(21 rows)
|
||||
|
||||
DROP TABLE prt;
|
||||
RESET enable_partitionwise_join;
|
||||
-- Exercise Memoize code that flushes the cache when a parameter changes which
|
||||
-- is not part of the cache key.
|
||||
-- Ensure we get a Memoize plan
|
||||
|
@ -104,6 +104,25 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false);
|
||||
|
||||
DROP TABLE strtest;
|
||||
|
||||
-- Ensure memoize works with partitionwise join
|
||||
SET enable_partitionwise_join TO on;
|
||||
|
||||
CREATE TABLE prt (a int) PARTITION BY RANGE(a);
|
||||
CREATE TABLE prt_p1 PARTITION OF prt FOR VALUES FROM (0) TO (10);
|
||||
CREATE TABLE prt_p2 PARTITION OF prt FOR VALUES FROM (10) TO (20);
|
||||
INSERT INTO prt VALUES (0), (0), (0), (0);
|
||||
INSERT INTO prt VALUES (10), (10), (10), (10);
|
||||
CREATE INDEX iprt_p1_a ON prt_p1 (a);
|
||||
CREATE INDEX iprt_p2_a ON prt_p2 (a);
|
||||
ANALYZE prt;
|
||||
|
||||
SELECT explain_memoize('
|
||||
SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false);
|
||||
|
||||
DROP TABLE prt;
|
||||
|
||||
RESET enable_partitionwise_join;
|
||||
|
||||
-- Exercise Memoize code that flushes the cache when a parameter changes which
|
||||
-- is not part of the cache key.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user