mirror of https://github.com/citusdata/citus.git
Perform range based pruning if equality pruning has survivor.
We previously dismissed this as unimportant, but it turns out to be very useful for the upcoming subquery pushdown, where a user might specify an equality constraint in a subquery, and the subquery pushdown machinery adds >= and <= restrictions on the shard boundary. Previously the latter restriction was ignored.support-6.1-faster-pruning
parent
7a0f02f186
commit
3ca7dd13be
|
@ -186,6 +186,9 @@ static List * PruneWithBoundaries(DistTableCacheEntry *cacheEntry,
|
||||||
static List * ExhaustivePrune(DistTableCacheEntry *cacheEntry,
|
static List * ExhaustivePrune(DistTableCacheEntry *cacheEntry,
|
||||||
ClauseWalkerContext *context,
|
ClauseWalkerContext *context,
|
||||||
PruningInstance *prune);
|
PruningInstance *prune);
|
||||||
|
static bool ExhaustivePruneOne(ShardInterval *curInterval,
|
||||||
|
ClauseWalkerContext *context,
|
||||||
|
PruningInstance *prune);
|
||||||
static int UpperShardBoundary(Datum partitionColumnValue,
|
static int UpperShardBoundary(Datum partitionColumnValue,
|
||||||
ShardInterval **shardIntervalCache,
|
ShardInterval **shardIntervalCache,
|
||||||
int shardCount, FunctionCallInfoData *compareFunction,
|
int shardCount, FunctionCallInfoData *compareFunction,
|
||||||
|
@ -894,14 +897,26 @@ PruneOne(DistTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If previous pruning method yielded a single shard, we could also
|
* If previous pruning method yielded a single shard, and the table is not
|
||||||
* attempt range based pruning to exclude it further. But that seems
|
* hash partitioned, attempt range based pruning to exclude it further.
|
||||||
* rarely useful in practice, and thus likely a waste of runtime and code
|
*
|
||||||
* complexity.
|
* That's particularly important in particular for subquery pushdown,
|
||||||
|
* where it's very common to have a user specified equality restriction,
|
||||||
|
* and a range based restriction for shard boundaries, added by the
|
||||||
|
* subquery machinery.
|
||||||
*/
|
*/
|
||||||
if (shardInterval)
|
if (shardInterval)
|
||||||
{
|
{
|
||||||
return list_make1(shardInterval);
|
if (context->partitionMethod != DISTRIBUTE_BY_HASH &&
|
||||||
|
ExhaustivePruneOne(shardInterval, context, prune))
|
||||||
|
{
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no chance to prune further, return */
|
||||||
|
return list_make1(shardInterval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1252,88 +1267,104 @@ ExhaustivePrune(DistTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
||||||
PruningInstance *prune)
|
PruningInstance *prune)
|
||||||
{
|
{
|
||||||
List *remainingShardList = NIL;
|
List *remainingShardList = NIL;
|
||||||
FunctionCallInfo compareFunctionCall = &context->compareIntervalFunctionCall;
|
|
||||||
int shardCount = cacheEntry->shardIntervalArrayLength;
|
int shardCount = cacheEntry->shardIntervalArrayLength;
|
||||||
ShardInterval **sortedShardIntervalArray = cacheEntry->sortedShardIntervalArray;
|
ShardInterval **sortedShardIntervalArray = cacheEntry->sortedShardIntervalArray;
|
||||||
int curIdx = 0;
|
int curIdx = 0;
|
||||||
|
|
||||||
for (curIdx = 0; curIdx < shardCount; curIdx++)
|
for (curIdx = 0; curIdx < shardCount; curIdx++)
|
||||||
{
|
{
|
||||||
Datum compareWith = 0;
|
|
||||||
ShardInterval *curInterval = sortedShardIntervalArray[curIdx];
|
ShardInterval *curInterval = sortedShardIntervalArray[curIdx];
|
||||||
|
|
||||||
/* NULL boundaries can't be compared to */
|
if (!ExhaustivePruneOne(curInterval, context, prune))
|
||||||
if (!curInterval->minValueExists || !curInterval->maxValueExists)
|
|
||||||
{
|
{
|
||||||
remainingShardList = lappend(remainingShardList, curInterval);
|
remainingShardList = lappend(remainingShardList, curInterval);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prune->equalConsts)
|
|
||||||
{
|
|
||||||
compareWith = prune->equalConsts->constvalue;
|
|
||||||
|
|
||||||
if (PerformValueCompare(compareFunctionCall,
|
|
||||||
compareWith,
|
|
||||||
curInterval->minValue) < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PerformValueCompare(compareFunctionCall,
|
|
||||||
compareWith,
|
|
||||||
curInterval->maxValue) > 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prune->greaterEqualConsts)
|
|
||||||
{
|
|
||||||
compareWith = prune->greaterEqualConsts->constvalue;
|
|
||||||
|
|
||||||
if (PerformValueCompare(compareFunctionCall,
|
|
||||||
curInterval->maxValue,
|
|
||||||
compareWith) < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prune->greaterConsts)
|
|
||||||
{
|
|
||||||
compareWith = prune->greaterConsts->constvalue;
|
|
||||||
|
|
||||||
if (PerformValueCompare(compareFunctionCall,
|
|
||||||
curInterval->maxValue,
|
|
||||||
compareWith) <= 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prune->lessEqualConsts)
|
|
||||||
{
|
|
||||||
compareWith = prune->lessEqualConsts->constvalue;
|
|
||||||
|
|
||||||
if (PerformValueCompare(compareFunctionCall,
|
|
||||||
curInterval->minValue,
|
|
||||||
compareWith) > 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prune->lessConsts)
|
|
||||||
{
|
|
||||||
compareWith = prune->lessConsts->constvalue;
|
|
||||||
|
|
||||||
if (PerformValueCompare(compareFunctionCall,
|
|
||||||
curInterval->minValue,
|
|
||||||
compareWith) >= 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remainingShardList = lappend(remainingShardList, curInterval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return remainingShardList;
|
return remainingShardList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ExhaustivePruneOne returns true if curInterval is pruned away, false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ExhaustivePruneOne(ShardInterval *curInterval,
|
||||||
|
ClauseWalkerContext *context,
|
||||||
|
PruningInstance *prune)
|
||||||
|
{
|
||||||
|
FunctionCallInfo compareFunctionCall = &context->compareIntervalFunctionCall;
|
||||||
|
Datum compareWith = 0;
|
||||||
|
|
||||||
|
/* NULL boundaries can't be compared to */
|
||||||
|
if (!curInterval->minValueExists || !curInterval->maxValueExists)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prune->equalConsts)
|
||||||
|
{
|
||||||
|
compareWith = prune->equalConsts->constvalue;
|
||||||
|
|
||||||
|
if (PerformValueCompare(compareFunctionCall,
|
||||||
|
compareWith,
|
||||||
|
curInterval->minValue) < 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PerformValueCompare(compareFunctionCall,
|
||||||
|
compareWith,
|
||||||
|
curInterval->maxValue) > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prune->greaterEqualConsts)
|
||||||
|
{
|
||||||
|
compareWith = prune->greaterEqualConsts->constvalue;
|
||||||
|
|
||||||
|
if (PerformValueCompare(compareFunctionCall,
|
||||||
|
curInterval->maxValue,
|
||||||
|
compareWith) < 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prune->greaterConsts)
|
||||||
|
{
|
||||||
|
compareWith = prune->greaterConsts->constvalue;
|
||||||
|
|
||||||
|
if (PerformValueCompare(compareFunctionCall,
|
||||||
|
curInterval->maxValue,
|
||||||
|
compareWith) <= 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prune->lessEqualConsts)
|
||||||
|
{
|
||||||
|
compareWith = prune->lessEqualConsts->constvalue;
|
||||||
|
|
||||||
|
if (PerformValueCompare(compareFunctionCall,
|
||||||
|
curInterval->minValue,
|
||||||
|
compareWith) > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prune->lessConsts)
|
||||||
|
{
|
||||||
|
compareWith = prune->lessConsts->constvalue;
|
||||||
|
|
||||||
|
if (PerformValueCompare(compareFunctionCall,
|
||||||
|
curInterval->minValue,
|
||||||
|
compareWith) >= 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue