Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 080313f

Browse files
author
Amit Kapila
committed
Don't shut down Gather[Merge] early under Limit.
Revert part of commit 19df170. Early shutdown was added by that commit so that we could collect statistics from workers, but unfortunately, it interacted badly with rescans. The problem is that we ended up destroying the parallel context which is required for rescans. This leads to rescans of a Limit node over a Gather node to produce unpredictable results as it tries to access destroyed parallel context. By reverting the early shutdown code, we might lose statistics in some cases of Limit over Gather [Merge], but that will require further study to fix. Reported-by: Jerry Sievers Diagnosed-by: Thomas Munro Author: Amit Kapila, testcase by Vignesh C Backpatch-through: 9.6 Discussion: https://postgr.es/m/87ims2amh6.fsf@jsievers.enova.com
1 parent 0d3c3aa commit 080313f

File tree

3 files changed

+67
-10
lines changed

3 files changed

+67
-10
lines changed

src/backend/executor/nodeLimit.c

+6-8
Original file line numberDiff line numberDiff line change
@@ -129,19 +129,17 @@ ExecLimit(PlanState *pstate)
129129
* we are at the end of the window, return NULL without
130130
* advancing the subplan or the position variable; but change
131131
* the state machine state to record having done so.
132+
*
133+
* Once at the end, ideally, we can shut down parallel
134+
* resources but that would destroy the parallel context which
135+
* would be required for rescans. To do that, we need to find
136+
* a way to pass down more information about whether rescans
137+
* are possible.
132138
*/
133139
if (!node->noCount &&
134140
node->position - node->offset >= node->count)
135141
{
136142
node->lstate = LIMIT_WINDOWEND;
137-
138-
/*
139-
* If we know we won't need to back up, we can release
140-
* resources at this point.
141-
*/
142-
if (!(node->ps.state->es_top_eflags & EXEC_FLAG_BACKWARD))
143-
(void) ExecShutdownNode(outerPlan);
144-
145143
return NULL;
146144
}
147145

src/test/regress/expected/select_parallel.out

+40-1
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,48 @@ select * from
455455
9000 | 3
456456
(3 rows)
457457

458-
reset enable_material;
458+
-- test rescans for a Limit node with a parallel node beneath it.
459459
reset enable_seqscan;
460+
set enable_indexonlyscan to off;
461+
set enable_indexscan to off;
462+
alter table tenk1 set (parallel_workers = 0);
463+
alter table tenk2 set (parallel_workers = 1);
464+
explain (costs off)
465+
select count(*) from tenk1
466+
left join (select tenk2.unique1 from tenk2 order by 1 limit 1000) ss
467+
on tenk1.unique1 < ss.unique1 + 1
468+
where tenk1.unique1 < 2;
469+
QUERY PLAN
470+
------------------------------------------------------------
471+
Aggregate
472+
-> Nested Loop Left Join
473+
Join Filter: (tenk1.unique1 < (tenk2.unique1 + 1))
474+
-> Seq Scan on tenk1
475+
Filter: (unique1 < 2)
476+
-> Limit
477+
-> Gather Merge
478+
Workers Planned: 1
479+
-> Sort
480+
Sort Key: tenk2.unique1
481+
-> Parallel Seq Scan on tenk2
482+
(11 rows)
483+
484+
select count(*) from tenk1
485+
left join (select tenk2.unique1 from tenk2 order by 1 limit 1000) ss
486+
on tenk1.unique1 < ss.unique1 + 1
487+
where tenk1.unique1 < 2;
488+
count
489+
-------
490+
1999
491+
(1 row)
492+
493+
--reset the value of workers for each table as it was before this test.
494+
alter table tenk1 set (parallel_workers = 4);
495+
alter table tenk2 reset (parallel_workers);
496+
reset enable_material;
460497
reset enable_bitmapscan;
498+
reset enable_indexonlyscan;
499+
reset enable_indexscan;
461500
-- test parallel bitmap heap scan.
462501
set enable_seqscan to off;
463502
set enable_indexscan to off;

src/test/regress/sql/select_parallel.sql

+21-1
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,29 @@ select * from
168168
(select count(*) from tenk1 where thousand > 99) ss
169169
right join (values (1),(2),(3)) v(x) on true;
170170

171-
reset enable_material;
171+
-- test rescans for a Limit node with a parallel node beneath it.
172172
reset enable_seqscan;
173+
set enable_indexonlyscan to off;
174+
set enable_indexscan to off;
175+
alter table tenk1 set (parallel_workers = 0);
176+
alter table tenk2 set (parallel_workers = 1);
177+
explain (costs off)
178+
select count(*) from tenk1
179+
left join (select tenk2.unique1 from tenk2 order by 1 limit 1000) ss
180+
on tenk1.unique1 < ss.unique1 + 1
181+
where tenk1.unique1 < 2;
182+
select count(*) from tenk1
183+
left join (select tenk2.unique1 from tenk2 order by 1 limit 1000) ss
184+
on tenk1.unique1 < ss.unique1 + 1
185+
where tenk1.unique1 < 2;
186+
--reset the value of workers for each table as it was before this test.
187+
alter table tenk1 set (parallel_workers = 4);
188+
alter table tenk2 reset (parallel_workers);
189+
190+
reset enable_material;
173191
reset enable_bitmapscan;
192+
reset enable_indexonlyscan;
193+
reset enable_indexscan;
174194

175195
-- test parallel bitmap heap scan.
176196
set enable_seqscan to off;

0 commit comments

Comments
 (0)