From 80558c1f5aa109d08db0fbd76a6d370f900628a8 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 11 Nov 2015 09:02:52 -0500 Subject: Generate parallel sequential scan plans in simple cases. Add a new flag, consider_parallel, to each RelOptInfo, indicating whether a plan for that relation could conceivably be run inside of a parallel worker. Right now, we're pretty conservative: for example, it might be possible to defer applying a parallel-restricted qual in a worker, and later do it in the leader, but right now we just don't try to parallelize access to that relation. That's probably the right decision in most cases, anyway. Using the new flag, generate parallel sequential scan plans for plain baserels, meaning that we now have parallel sequential scan in PostgreSQL. The logic here is pretty unsophisticated right now: the costing model probably isn't right in detail, and we can't push joins beneath Gather nodes, so the number of plans that can actually benefit from this is pretty limited right now. Lots more work is needed. Nevertheless, it seems time to enable this functionality so that all this code can actually be tested easily by users and developers. Note that, if you wish to test this functionality, it will be necessary to set max_parallel_degree to a value greater than the default of 0. Once a few more loose ends have been tidied up here, we might want to consider changing the default value of this GUC, but I'm leaving it alone for now. Along the way, fix a bug in cost_gather: the previous coding thought that a Gather node's transfer overhead should be costed on the basis of the relation size rather than the number of tuples that actually need to be passed off to the leader. Patch by me, reviewed in earlier versions by Amit Kapila. --- src/backend/optimizer/util/relnode.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/backend/optimizer/util/relnode.c') diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 68a93a1a5b..996b7fe513 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -14,6 +14,7 @@ */ #include "postgres.h" +#include "optimizer/clauses.h" #include "optimizer/cost.h" #include "optimizer/pathnode.h" #include "optimizer/paths.h" @@ -102,6 +103,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) /* cheap startup cost is interesting iff not all tuples to be retrieved */ rel->consider_startup = (root->tuple_fraction > 0); rel->consider_param_startup = false; /* might get changed later */ + rel->consider_parallel = false; /* might get changed later */ rel->reltargetlist = NIL; rel->pathlist = NIL; rel->ppilist = NIL; @@ -363,6 +365,7 @@ build_join_rel(PlannerInfo *root, /* cheap startup cost is interesting iff not all tuples to be retrieved */ joinrel->consider_startup = (root->tuple_fraction > 0); joinrel->consider_param_startup = false; + joinrel->consider_parallel = false; joinrel->reltargetlist = NIL; joinrel->pathlist = NIL; joinrel->ppilist = NIL; @@ -441,6 +444,24 @@ build_join_rel(PlannerInfo *root, set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel, sjinfo, restrictlist); + /* + * Set the consider_parallel flag if this joinrel could potentially be + * scanned within a parallel worker. If this flag is false for either + * inner_rel or outer_rel, then it must be false for the joinrel also. + * Even if both are true, there might be parallel-restricted quals at + * our level. + * + * Note that if there are more than two rels in this relation, they + * could be divided between inner_rel and outer_rel in any arbitary + * way. We assume this doesn't matter, because we should hit all the + * same baserels and joinclauses while building up to this joinrel no + * matter which we take; therefore, we should make the same decision + * here however we get here. + */ + if (inner_rel->consider_parallel && outer_rel->consider_parallel && + !has_parallel_hazard((Node *) restrictlist, false)) + joinrel->consider_parallel = true; + /* * Add the joinrel to the query's joinrel list, and store it into the * auxiliary hashtable if there is one. NB: GEQO requires us to append -- cgit v1.2.1