mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Improve planner's ability to recognize cases where an IN's RHS is unique.
If the right-hand side of a semijoin is unique, then we can treat it like a normal join (or another way to say that is: we don't need to explicitly unique-ify the data before doing it as a normal join). We were recognizing such cases when the RHS was a sub-query with appropriate DISTINCT or GROUP BY decoration, but there's another way: if the RHS is a plain relation with unique indexes, we can check if any of the indexes prove the output is unique. Most of the infrastructure for that was there already in the join removal code, though I had to rearrange it a bit. Per reflection about a recent example in pgsql-performance.
This commit is contained in:
@ -264,42 +264,13 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
|
||||
clause_list = lappend(clause_list, restrictinfo);
|
||||
}
|
||||
|
||||
/* Now examine the rel's restriction clauses for var = const clauses */
|
||||
foreach(l, innerrel->baserestrictinfo)
|
||||
{
|
||||
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
|
||||
|
||||
/*
|
||||
* Note: can_join won't be set for a restriction clause, but
|
||||
* mergeopfamilies will be if it has a mergejoinable operator and
|
||||
* doesn't contain volatile functions.
|
||||
*/
|
||||
if (restrictinfo->mergeopfamilies == NIL)
|
||||
continue; /* not mergejoinable */
|
||||
|
||||
/*
|
||||
* The clause certainly doesn't refer to anything but the given rel.
|
||||
* If either side is pseudoconstant then we can use it.
|
||||
*/
|
||||
if (bms_is_empty(restrictinfo->left_relids))
|
||||
{
|
||||
/* righthand side is inner */
|
||||
restrictinfo->outer_is_left = true;
|
||||
}
|
||||
else if (bms_is_empty(restrictinfo->right_relids))
|
||||
{
|
||||
/* lefthand side is inner */
|
||||
restrictinfo->outer_is_left = false;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
/* OK, add to list */
|
||||
clause_list = lappend(clause_list, restrictinfo);
|
||||
}
|
||||
/*
|
||||
* relation_has_unique_index_for automatically adds any usable restriction
|
||||
* clauses for the innerrel, so we needn't do that here.
|
||||
*/
|
||||
|
||||
/* Now examine the indexes to see if we have a matching unique index */
|
||||
if (relation_has_unique_index_for(root, innerrel, clause_list))
|
||||
if (relation_has_unique_index_for(root, innerrel, clause_list, NIL, NIL))
|
||||
return true;
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user