mirror of https://github.com/citusdata/citus.git
Merge pull request #4264 from citusdata/remove_remove_duplicate
Remove RemoveDuplicateJoinRestrictions() functionpull/4267/head
commit
808f30c1a2
|
@ -615,8 +615,6 @@ CreateDistributedPlannedStmt(DistributedPlanningContext *planContext)
|
||||||
{
|
{
|
||||||
uint64 planId = NextPlanId++;
|
uint64 planId = NextPlanId++;
|
||||||
bool hasUnresolvedParams = false;
|
bool hasUnresolvedParams = false;
|
||||||
JoinRestrictionContext *joinRestrictionContext =
|
|
||||||
planContext->plannerRestrictionContext->joinRestrictionContext;
|
|
||||||
|
|
||||||
PlannedStmt *resultPlan = NULL;
|
PlannedStmt *resultPlan = NULL;
|
||||||
|
|
||||||
|
@ -646,9 +644,6 @@ CreateDistributedPlannedStmt(DistributedPlanningContext *planContext)
|
||||||
hasUnresolvedParams = true;
|
hasUnresolvedParams = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
planContext->plannerRestrictionContext->joinRestrictionContext =
|
|
||||||
RemoveDuplicateJoinRestrictions(joinRestrictionContext);
|
|
||||||
|
|
||||||
DistributedPlan *distributedPlan =
|
DistributedPlan *distributedPlan =
|
||||||
CreateDistributedPlan(planId, planContext->originalQuery, planContext->query,
|
CreateDistributedPlan(planId, planContext->originalQuery, planContext->query,
|
||||||
planContext->boundParams,
|
planContext->boundParams,
|
||||||
|
@ -1744,8 +1739,6 @@ multi_join_restriction_hook(PlannerInfo *root,
|
||||||
*/
|
*/
|
||||||
joinRestrictionContext->hasSemiJoin = joinRestrictionContext->hasSemiJoin ||
|
joinRestrictionContext->hasSemiJoin = joinRestrictionContext->hasSemiJoin ||
|
||||||
extra->sjinfo->jointype == JOIN_SEMI;
|
extra->sjinfo->jointype == JOIN_SEMI;
|
||||||
joinRestrictionContext->hasOnlyInnerJoin = joinRestrictionContext->hasOnlyInnerJoin &&
|
|
||||||
extra->sjinfo->jointype == JOIN_INNER;
|
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldMemoryContext);
|
MemoryContextSwitchTo(oldMemoryContext);
|
||||||
}
|
}
|
||||||
|
@ -2135,7 +2128,6 @@ CreateAndPushPlannerRestrictionContext(void)
|
||||||
|
|
||||||
/* we'll apply logical AND as we add tables */
|
/* we'll apply logical AND as we add tables */
|
||||||
plannerRestrictionContext->relationRestrictionContext->allReferenceTables = true;
|
plannerRestrictionContext->relationRestrictionContext->allReferenceTables = true;
|
||||||
plannerRestrictionContext->joinRestrictionContext->hasOnlyInnerJoin = true;
|
|
||||||
|
|
||||||
plannerRestrictionContextList = lcons(plannerRestrictionContext,
|
plannerRestrictionContextList = lcons(plannerRestrictionContext,
|
||||||
plannerRestrictionContextList);
|
plannerRestrictionContextList);
|
||||||
|
|
|
@ -151,8 +151,6 @@ static bool RangeTableArrayContainsAnyRTEIdentities(RangeTblEntry **rangeTableEn
|
||||||
queryRteIdentities);
|
queryRteIdentities);
|
||||||
static int RangeTableOffsetCompat(PlannerInfo *root, AppendRelInfo *appendRelInfo);
|
static int RangeTableOffsetCompat(PlannerInfo *root, AppendRelInfo *appendRelInfo);
|
||||||
static Relids QueryRteIdentities(Query *queryTree);
|
static Relids QueryRteIdentities(Query *queryTree);
|
||||||
static bool ContextCoversJoinRestriction(JoinRestrictionContext *joinRestrictionContext,
|
|
||||||
JoinRestriction *joinRestrictionInTest);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1910,8 +1908,6 @@ FilterJoinRestrictionContext(JoinRestrictionContext *joinRestrictionContext, Rel
|
||||||
* No need to re calculate has join fields as we are still operating on
|
* No need to re calculate has join fields as we are still operating on
|
||||||
* the same query and as these values are calculated per-query basis.
|
* the same query and as these values are calculated per-query basis.
|
||||||
*/
|
*/
|
||||||
filtererdJoinRestrictionContext->hasOnlyInnerJoin =
|
|
||||||
joinRestrictionContext->hasOnlyInnerJoin;
|
|
||||||
filtererdJoinRestrictionContext->hasSemiJoin = joinRestrictionContext->hasSemiJoin;
|
filtererdJoinRestrictionContext->hasSemiJoin = joinRestrictionContext->hasSemiJoin;
|
||||||
|
|
||||||
return filtererdJoinRestrictionContext;
|
return filtererdJoinRestrictionContext;
|
||||||
|
@ -2000,105 +1996,3 @@ QueryRteIdentities(Query *queryTree)
|
||||||
|
|
||||||
return queryRteIdentities;
|
return queryRteIdentities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* RemoveDuplicateJoinRestrictions gets a join restriction context and returns a
|
|
||||||
* newly allocated join restriction context where the duplicate join restrictions
|
|
||||||
* removed.
|
|
||||||
*
|
|
||||||
* Note that we use PostgreSQL hooks to accumulate the join restrictions and PostgreSQL
|
|
||||||
* gives us all the join paths it tries while deciding on the join order. Thus, for
|
|
||||||
* queries that has many joins, this function is likely to remove lots of duplicate join
|
|
||||||
* restrictions. This becomes relevant for Citus on query pushdown check peformance.
|
|
||||||
*/
|
|
||||||
JoinRestrictionContext *
|
|
||||||
RemoveDuplicateJoinRestrictions(JoinRestrictionContext *joinRestrictionContext)
|
|
||||||
{
|
|
||||||
JoinRestrictionContext *filteredContext = palloc0(sizeof(JoinRestrictionContext));
|
|
||||||
ListCell *joinRestrictionCell = NULL;
|
|
||||||
|
|
||||||
filteredContext->joinRestrictionList = NIL;
|
|
||||||
|
|
||||||
foreach(joinRestrictionCell, joinRestrictionContext->joinRestrictionList)
|
|
||||||
{
|
|
||||||
JoinRestriction *joinRestriction = lfirst(joinRestrictionCell);
|
|
||||||
|
|
||||||
if (ContextCoversJoinRestriction(filteredContext, joinRestriction))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredContext->joinRestrictionList =
|
|
||||||
lappend(filteredContext->joinRestrictionList, joinRestriction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* No need to re calculate has join fields as we are still operating on
|
|
||||||
* the same query and as these values are calculated per-query basis.
|
|
||||||
*/
|
|
||||||
filteredContext->hasOnlyInnerJoin = joinRestrictionContext->hasOnlyInnerJoin;
|
|
||||||
filteredContext->hasSemiJoin = joinRestrictionContext->hasSemiJoin;
|
|
||||||
|
|
||||||
return filteredContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ContextCoversJoinRestriction returns true if the given joinRestriction
|
|
||||||
* has an equivalent of in the given joinRestrictionContext.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
ContextCoversJoinRestriction(JoinRestrictionContext *joinRestrictionContext,
|
|
||||||
JoinRestriction *joinRestrictionInTest)
|
|
||||||
{
|
|
||||||
JoinRestriction *joinRestrictionInContext = NULL;
|
|
||||||
List *joinRestrictionInContextList = joinRestrictionContext->joinRestrictionList;
|
|
||||||
foreach_ptr(joinRestrictionInContext, joinRestrictionInContextList)
|
|
||||||
{
|
|
||||||
/* obviously we shouldn't treat different join types as being the same */
|
|
||||||
if (joinRestrictionInContext->joinType != joinRestrictionInTest->joinType)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're dealing with different queries, we shouldn't treat their
|
|
||||||
* restrictions as being the same.
|
|
||||||
*/
|
|
||||||
if (joinRestrictionInContext->plannerInfo != joinRestrictionInTest->plannerInfo)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
List *joinRestrictInfoListInTest =
|
|
||||||
joinRestrictionInTest->joinRestrictInfoList;
|
|
||||||
bool hasJoinRestriction = list_length(joinRestrictInfoListInTest) > 0;
|
|
||||||
bool hasOnlyInnerJoin = joinRestrictionContext->hasOnlyInnerJoin;
|
|
||||||
if (!hasOnlyInnerJoin && !hasJoinRestriction)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If join doesn't have a restriction (e.g., ON (true)) and planner
|
|
||||||
* is aware of at least one non-inner JOIN (e.g., outer/semi joins),
|
|
||||||
* we should not eliminiate joinRestrictionInTest. It can still be
|
|
||||||
* useful for detecting not supported outer-join checks even if it
|
|
||||||
* doesn't help for colocation checks.
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We check whether the restrictions in joinRestrictionInTest is a subset
|
|
||||||
* of the restrictions in joinRestrictionInContext in the sense that all the
|
|
||||||
* restrictions in the latter already exists in the former.
|
|
||||||
*/
|
|
||||||
List *joinRestrictInfoListInContext =
|
|
||||||
joinRestrictionInContext->joinRestrictInfoList;
|
|
||||||
if (LeftListIsSubset(joinRestrictInfoListInTest, joinRestrictInfoListInContext))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
|
@ -258,15 +258,3 @@ GenerateListFromElement(void *listElement, int listLength)
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* LeftListIsSubset returns true if lhs is subset of rhs list. Note that input
|
|
||||||
* lists' entries should implement equal() function.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
LeftListIsSubset(const List *lhs, const List *rhs)
|
|
||||||
{
|
|
||||||
List *listDifference = list_difference(lhs, rhs);
|
|
||||||
return list_length(listDifference) == 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -76,7 +76,6 @@ typedef struct JoinRestrictionContext
|
||||||
{
|
{
|
||||||
List *joinRestrictionList;
|
List *joinRestrictionList;
|
||||||
bool hasSemiJoin;
|
bool hasSemiJoin;
|
||||||
bool hasOnlyInnerJoin;
|
|
||||||
} JoinRestrictionContext;
|
} JoinRestrictionContext;
|
||||||
|
|
||||||
typedef struct JoinRestriction
|
typedef struct JoinRestriction
|
||||||
|
|
|
@ -93,6 +93,5 @@ extern List * ListTake(List *pointerList, int size);
|
||||||
extern void * safe_list_nth(const List *list, int index);
|
extern void * safe_list_nth(const List *list, int index);
|
||||||
extern List * GeneratePositiveIntSequenceList(int upTo);
|
extern List * GeneratePositiveIntSequenceList(int upTo);
|
||||||
extern List * GenerateListFromElement(void *listElement, int listLength);
|
extern List * GenerateListFromElement(void *listElement, int listLength);
|
||||||
extern bool LeftListIsSubset(const List *lhs, const List *rhs);
|
|
||||||
|
|
||||||
#endif /* CITUS_LISTUTILS_H */
|
#endif /* CITUS_LISTUTILS_H */
|
||||||
|
|
|
@ -36,9 +36,6 @@ extern List * DistributedRelationIdList(Query *query);
|
||||||
extern PlannerRestrictionContext * FilterPlannerRestrictionForQuery(
|
extern PlannerRestrictionContext * FilterPlannerRestrictionForQuery(
|
||||||
PlannerRestrictionContext *plannerRestrictionContext,
|
PlannerRestrictionContext *plannerRestrictionContext,
|
||||||
Query *query);
|
Query *query);
|
||||||
extern JoinRestrictionContext * RemoveDuplicateJoinRestrictions(JoinRestrictionContext *
|
|
||||||
joinRestrictionContext);
|
|
||||||
|
|
||||||
extern bool EquivalenceListContainsRelationsEquality(List *attributeEquivalenceList,
|
extern bool EquivalenceListContainsRelationsEquality(List *attributeEquivalenceList,
|
||||||
RelationRestrictionContext *
|
RelationRestrictionContext *
|
||||||
restrictionContext);
|
restrictionContext);
|
||||||
|
|
Loading…
Reference in New Issue