summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/orindxpath.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-04-19 15:52:46 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-04-19 15:53:47 -0400
commit5b7b5518d0ea56c422a197875f7efa5deddbb388 (patch)
tree1e647989f2f6399fff7fe68a493200ccf9d2b01f /src/backend/optimizer/path/orindxpath.c
parentcd1f4db4aec0c4b71d2ed0d29bbe388dfcd11527 (diff)
Revise parameterized-path mechanism to fix assorted issues.
This patch adjusts the treatment of parameterized paths so that all paths with the same parameterization (same set of required outer rels) for the same relation will have the same rowcount estimate. We cache the rowcount estimates to ensure that property, and hopefully save a few cycles too. Doing this makes it practical for add_path_precheck to operate without a rowcount estimate: it need only assume that paths with different parameterizations never dominate each other, which is close enough to true anyway for coarse filtering, because normally a more-parameterized path should yield fewer rows thanks to having more join clauses to apply. In add_path, we do the full nine yards of comparing rowcount estimates along with everything else, so that we can discard parameterized paths that don't actually have an advantage. This fixes some issues I'd found with add_path rejecting parameterized paths on the grounds that they were more expensive than not-parameterized ones, even though they yielded many fewer rows and hence would be cheaper once subsequent joining was considered. To make the same-rowcounts assumption valid, we have to require that any parameterized path enforce *all* join clauses that could be obtained from the particular set of outer rels, even if not all of them are useful for indexing. This is required at both base scans and joins. It's a good thing anyway since the net impact is that join quals are checked at the lowest practical level in the join tree. Hence, discard the original rather ad-hoc mechanism for choosing parameterization joinquals, and build a better one that has a more principled rule for when clauses can be moved. The original rule was actually buggy anyway for lack of knowledge about which relations are part of an outer join's outer side; getting this right requires adding an outer_relids field to RestrictInfo.
Diffstat (limited to 'src/backend/optimizer/path/orindxpath.c')
-rw-r--r--src/backend/optimizer/path/orindxpath.c21
1 files changed, 6 insertions, 15 deletions
diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c
index 02bd362c5c8..cab79518919 100644
--- a/src/backend/optimizer/path/orindxpath.c
+++ b/src/backend/optimizer/path/orindxpath.c
@@ -67,7 +67,7 @@
* Path for a given relation generates the same number of rows. Without
* this assumption we'd not be able to optimize solely on the cost of Paths,
* but would have to take number of output rows into account as well.
- * (Perhaps someday that'd be worth doing, but it's a pretty big change...)
+ * (The parameterized-paths stuff almost fixes this, but not quite...)
*
* 'rel' is the relation entry for which quals are to be created
*
@@ -93,26 +93,17 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel)
return false;
/*
- * Find potentially interesting OR joinclauses.
- *
- * We must ignore clauses for which the target rel is in nullable_relids;
- * that means there's an outer join below the clause and so it can't be
- * enforced at the relation scan level.
- *
- * We must also ignore clauses that are marked !is_pushed_down (ie they
- * are themselves outer-join clauses). It would be safe to extract an
- * index condition from such a clause if we are within the nullable rather
- * than the non-nullable side of its join, but we haven't got enough
- * context here to tell which applies. OR clauses in outer-join quals
- * aren't exactly common, so we'll let that case go unoptimized for now.
+ * Find potentially interesting OR joinclauses. We can use any joinclause
+ * that is considered safe to move to this rel by the parameterized-path
+ * machinery, even though what we are going to do with it is not exactly
+ * a parameterized path.
*/
foreach(i, rel->joininfo)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
if (restriction_is_or_clause(rinfo) &&
- rinfo->is_pushed_down &&
- !bms_is_member(rel->relid, rinfo->nullable_relids))
+ join_clause_is_movable_to(rinfo, rel->relid))
{
/*
* Use the generate_bitmap_or_paths() machinery to estimate the