mirror of https://github.com/citusdata/citus.git
Merge pull request #1369 from citusdata/featurefix/better-range-pruning
Improve / Fix range pruningpull/1323/head
commit
0cc9171984
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1158,9 +1173,19 @@ PruneWithBoundaries(DistTableCacheEntry *cacheEntry, ClauseWalkerContext *contex
|
||||||
}
|
}
|
||||||
if (prune->greaterConsts)
|
if (prune->greaterConsts)
|
||||||
{
|
{
|
||||||
lowerBound = prune->greaterConsts->constvalue;
|
/*
|
||||||
lowerBoundInclusive = false;
|
* Use the more restrictive one, if both greater and greaterEqual
|
||||||
hasLowerBound = true;
|
* constraints are specified.
|
||||||
|
*/
|
||||||
|
if (!hasLowerBound ||
|
||||||
|
PerformValueCompare(compareFunctionCall,
|
||||||
|
prune->greaterConsts->constvalue,
|
||||||
|
lowerBound) >= 0)
|
||||||
|
{
|
||||||
|
lowerBound = prune->greaterConsts->constvalue;
|
||||||
|
lowerBoundInclusive = false;
|
||||||
|
hasLowerBound = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (prune->lessEqualConsts)
|
if (prune->lessEqualConsts)
|
||||||
{
|
{
|
||||||
|
@ -1170,9 +1195,19 @@ PruneWithBoundaries(DistTableCacheEntry *cacheEntry, ClauseWalkerContext *contex
|
||||||
}
|
}
|
||||||
if (prune->lessConsts)
|
if (prune->lessConsts)
|
||||||
{
|
{
|
||||||
upperBound = prune->lessConsts->constvalue;
|
/*
|
||||||
upperBoundInclusive = false;
|
* Use the more restrictive one, if both less and lessEqual
|
||||||
hasUpperBound = true;
|
* constraints are specified.
|
||||||
|
*/
|
||||||
|
if (!hasUpperBound ||
|
||||||
|
PerformValueCompare(compareFunctionCall,
|
||||||
|
prune->lessConsts->constvalue,
|
||||||
|
upperBound) <= 0)
|
||||||
|
{
|
||||||
|
upperBound = prune->lessConsts->constvalue;
|
||||||
|
upperBoundInclusive = false;
|
||||||
|
hasUpperBound = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(hasLowerBound || hasUpperBound);
|
Assert(hasLowerBound || hasUpperBound);
|
||||||
|
@ -1232,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