mirror of
https://github.com/postgres/postgres.git
synced 2025-05-08 07:21:33 +03:00
Fix parallel query so it doesn't spoil row estimates above Gather.
Commit 45be99f8cd5d606086e0a458c9c72910ba8a613d removed GatherPath's num_workers field, but this is entirely bogus. Normally, a path's parallel_workers flag is supposed to indicate the number of workers that it wants, and should be 0 for a non-partial path. In that commit, I mistakenly thought that GatherPath could also use that field to indicate the number of workers that it would try to start, but that's disastrous, because then it can propagate up to higher nodes in the plan tree, which will then get incorrect rowcounts because the parallel_workers flag is involved in computing those values. Repair by putting the separate field back. Report by Tomas Vondra. Patch by me, reviewed by Amit Kapila. Discussion: http://postgr.es/m/f91b4a44-f739-04bd-c4b6-f135bd643669@2ndquadrant.com
This commit is contained in:
parent
9b6e8d8f86
commit
fb1879c374
@ -1795,6 +1795,7 @@ _outGatherPath(StringInfo str, const GatherPath *node)
|
|||||||
|
|
||||||
WRITE_NODE_FIELD(subpath);
|
WRITE_NODE_FIELD(subpath);
|
||||||
WRITE_BOOL_FIELD(single_copy);
|
WRITE_BOOL_FIELD(single_copy);
|
||||||
|
WRITE_INT_FIELD(num_workers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1395,7 +1395,7 @@ create_gather_plan(PlannerInfo *root, GatherPath *best_path)
|
|||||||
|
|
||||||
gather_plan = make_gather(tlist,
|
gather_plan = make_gather(tlist,
|
||||||
NIL,
|
NIL,
|
||||||
best_path->path.parallel_workers,
|
best_path->num_workers,
|
||||||
best_path->single_copy,
|
best_path->single_copy,
|
||||||
subplan);
|
subplan);
|
||||||
|
|
||||||
|
@ -1681,16 +1681,17 @@ create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
|
|||||||
required_outer);
|
required_outer);
|
||||||
pathnode->path.parallel_aware = false;
|
pathnode->path.parallel_aware = false;
|
||||||
pathnode->path.parallel_safe = false;
|
pathnode->path.parallel_safe = false;
|
||||||
pathnode->path.parallel_workers = subpath->parallel_workers;
|
pathnode->path.parallel_workers = 0;
|
||||||
pathnode->path.pathkeys = NIL; /* Gather has unordered result */
|
pathnode->path.pathkeys = NIL; /* Gather has unordered result */
|
||||||
|
|
||||||
pathnode->subpath = subpath;
|
pathnode->subpath = subpath;
|
||||||
|
pathnode->num_workers = subpath->parallel_workers;
|
||||||
pathnode->single_copy = false;
|
pathnode->single_copy = false;
|
||||||
|
|
||||||
if (pathnode->path.parallel_workers == 0)
|
if (pathnode->num_workers == 0)
|
||||||
{
|
{
|
||||||
pathnode->path.parallel_workers = 1;
|
|
||||||
pathnode->path.pathkeys = subpath->pathkeys;
|
pathnode->path.pathkeys = subpath->pathkeys;
|
||||||
|
pathnode->num_workers = 1;
|
||||||
pathnode->single_copy = true;
|
pathnode->single_copy = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1189,6 +1189,7 @@ typedef struct GatherPath
|
|||||||
Path path;
|
Path path;
|
||||||
Path *subpath; /* path for each worker */
|
Path *subpath; /* path for each worker */
|
||||||
bool single_copy; /* path must not be executed >1x */
|
bool single_copy; /* path must not be executed >1x */
|
||||||
|
int num_workers; /* number of workers sought to help */
|
||||||
} GatherPath;
|
} GatherPath;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user