diff options
| author | Tom Lane | 2017-04-08 02:20:03 +0000 |
|---|---|---|
| committer | Tom Lane | 2017-04-08 02:20:13 +0000 |
| commit | 9c7f5229ad68d7e0e4dd149e3f80257893e404d4 (patch) | |
| tree | 0a167d403952550f43941b01b24ed5e7526c5351 /src/backend/nodes | |
| parent | f13a9121f9822eafe05cc3178bf046155a248173 (diff) | |
Optimize joins when the inner relation can be proven unique.
If there can certainly be no more than one matching inner row for a given
outer row, then the executor can move on to the next outer row as soon as
it's found one match; there's no need to continue scanning the inner
relation for this outer row. This saves useless scanning in nestloop
and hash joins. In merge joins, it offers the opportunity to skip
mark/restore processing, because we know we have not advanced past the
first possible match for the next outer row.
Of course, the devil is in the details: the proof of uniqueness must
depend only on joinquals (not otherquals), and if we want to skip
mergejoin mark/restore then it must depend only on merge clauses.
To avoid adding more planning overhead than absolutely necessary,
the present patch errs in the conservative direction: there are cases
where inner_unique or skip_mark_restore processing could be used, but
it will not do so because it's not sure that the uniqueness proof
depended only on "safe" clauses. This could be improved later.
David Rowley, reviewed and rather heavily editorialized on by me
Discussion: https://postgr.es/m/CAApHDvqF6Sw-TK98bW48TdtFJ+3a7D2mFyZ7++=D-RyPsL76gw@mail.gmail.com
Diffstat (limited to 'src/backend/nodes')
| -rw-r--r-- | src/backend/nodes/copyfuncs.c | 2 | ||||
| -rw-r--r-- | src/backend/nodes/outfuncs.c | 5 | ||||
| -rw-r--r-- | src/backend/nodes/readfuncs.c | 2 |
3 files changed, 9 insertions, 0 deletions
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 96619da8a9..2cb8b3b5ea 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -797,6 +797,7 @@ CopyJoinFields(const Join *from, Join *newnode) CopyPlanFields((const Plan *) from, (Plan *) newnode); COPY_SCALAR_FIELD(jointype); + COPY_SCALAR_FIELD(inner_unique); COPY_NODE_FIELD(joinqual); } @@ -857,6 +858,7 @@ _copyMergeJoin(const MergeJoin *from) /* * copy remainder of node */ + COPY_SCALAR_FIELD(skip_mark_restore); COPY_NODE_FIELD(mergeclauses); numCols = list_length(from->mergeclauses); if (numCols > 0) diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 13672979b4..84657cbae9 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -305,6 +305,7 @@ _outJoinPlanInfo(StringInfo str, const Join *node) _outPlanInfo(str, (const Plan *) node); WRITE_ENUM_FIELD(jointype, JoinType); + WRITE_BOOL_FIELD(inner_unique); WRITE_NODE_FIELD(joinqual); } @@ -714,6 +715,7 @@ _outMergeJoin(StringInfo str, const MergeJoin *node) _outJoinPlanInfo(str, (const Join *) node); + WRITE_BOOL_FIELD(skip_mark_restore); WRITE_NODE_FIELD(mergeclauses); numCols = list_length(node->mergeclauses); @@ -1707,6 +1709,7 @@ _outJoinPathInfo(StringInfo str, const JoinPath *node) _outPathInfo(str, (const Path *) node); WRITE_ENUM_FIELD(jointype, JoinType); + WRITE_BOOL_FIELD(inner_unique); WRITE_NODE_FIELD(outerjoinpath); WRITE_NODE_FIELD(innerjoinpath); WRITE_NODE_FIELD(joinrestrictinfo); @@ -2114,6 +2117,7 @@ _outMergePath(StringInfo str, const MergePath *node) WRITE_NODE_FIELD(path_mergeclauses); WRITE_NODE_FIELD(outersortkeys); WRITE_NODE_FIELD(innersortkeys); + WRITE_BOOL_FIELD(skip_mark_restore); WRITE_BOOL_FIELD(materialize_inner); } @@ -2246,6 +2250,7 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node) WRITE_OID_FIELD(userid); WRITE_BOOL_FIELD(useridiscurrent); /* we don't try to print fdwroutine or fdw_private */ + /* can't print unique_for_rels/non_unique_for_rels; BMSes aren't Nodes */ WRITE_NODE_FIELD(baserestrictinfo); WRITE_UINT_FIELD(baserestrict_min_security); WRITE_NODE_FIELD(joininfo); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index e027154e67..c93a947ee2 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1949,6 +1949,7 @@ ReadCommonJoin(Join *local_node) ReadCommonPlan(&local_node->plan); READ_ENUM_FIELD(jointype, JoinType); + READ_BOOL_FIELD(inner_unique); READ_NODE_FIELD(joinqual); } @@ -1992,6 +1993,7 @@ _readMergeJoin(void) ReadCommonJoin(&local_node->join); + READ_BOOL_FIELD(skip_mark_restore); READ_NODE_FIELD(mergeclauses); numCols = list_length(local_node->mergeclauses); |
