use patternmatcher for join pushdown

moonshot/custom-path
Nils Dijk 2021-07-21 17:29:23 +02:00
parent f4c5f9e2ea
commit 7ee4646e96
No known key found for this signature in database
GPG Key ID: CA1177EF9434F241
1 changed files with 55 additions and 71 deletions

View File

@ -72,7 +72,6 @@ static List * BroadcastOuterJoinPath(PlannerInfo *root, Path *originalPath);
static List * BroadcastInnerJoinPath(PlannerInfo *root, Path *originalPath);
static List * GeoOverlapJoin(PlannerInfo *root, Path *originalPath);
static Path * CreateReadIntermediateResultPath(const Path *originalPath);
static bool CanOptimizeJoinPath(const JoinPath *jpath);
static bool IsDistributedUnion(Path *path, bool recurseTransparent,
DistributedUnionPath **out);
static Expr * ExtractPartitionValue(List *restrictionList, Var *partitionKey);
@ -684,35 +683,6 @@ ExtractPartitionValue(List *restrictionList, Var *partitionKey)
}
static bool
CanOptimizeJoinPath(const JoinPath *jpath)
{
if (!(IsDistributedUnion(jpath->innerjoinpath, false, NULL) &&
IsDistributedUnion(jpath->outerjoinpath, false, NULL)))
{
/* can only optimize joins when both inner and outer are a distributed union */
return false;
}
DistributedUnionPath *innerDU = (DistributedUnionPath *) jpath->innerjoinpath;
DistributedUnionPath *outerDU = (DistributedUnionPath *) jpath->outerjoinpath;
if (innerDU->colocationId != outerDU->colocationId)
{
/* Distributed Union is not on the same colocation group */
return false;
}
if (!equal(innerDU->partitionValue, outerDU->partitionValue))
{
/* TODO this is most likely too strict, but if the values are strictly the same we can easily take one during merging */
return false;
}
return true;
}
static NameData
GetFunctionNameData(Oid funcid)
{
@ -889,33 +859,52 @@ GeoOverlapJoin(PlannerInfo *root, Path *originalPath)
static List *
OptimizeJoinPath(PlannerInfo *root, Path *originalPath)
{
switch (originalPath->pathtype)
{
case T_NestLoop:
case T_HashJoin:
{
const JoinPath *jpath = (JoinPath *) originalPath;
if (jpath->jointype == JOIN_INNER && CanOptimizeJoinPath(jpath))
{
/* we can only optimize the Distributed union if the colocationId's are the same, taking any would suffice */
DistributedUnionPath *baseDistUnion =
(DistributedUnionPath *) jpath->innerjoinpath;
DistributedUnionPath *innerDU = NULL;
DistributedUnionPath *outerDU = NULL;
JoinPath *jpath = NULL;
IfPathMatch(
originalPath,
MatchJoin(
&jpath,
JOIN_INNER,
/* match on join restriction info */
MatchAny,
/* match inner path in join */
SkipReadThrough(
NoCapture,
MatchDistributedUnion(
&innerDU,
MatchAny)),
/* match outer path in join */
SkipReadThrough(
NoCapture,
MatchDistributedUnion(
&outerDU,
MatchAny))))
{
if (innerDU->colocationId != outerDU->colocationId)
{
/* Distributed Union is not on the same colocation group */
return NIL;
}
if (!equal(innerDU->partitionValue, outerDU->partitionValue))
{
/* TODO this is most likely too strict, but if the values are strictly the same we can easily take one during merging */
return NIL;
}
const DistributedUnionPath *baseDistUnion = innerDU;
/*
* Shallow copy of any join node, this does not imply executing a nested
* join, but the nested join contains all the information we need to send
* the join to the worker
*/
JoinPath *jcpath = makeNode(NestPath);
*jcpath = *jpath;
jcpath->path.type = T_NestPath;
jcpath->innerjoinpath =
((DistributedUnionPath *) jpath->innerjoinpath)->worker_path;
jcpath->outerjoinpath =
((DistributedUnionPath *) jpath->outerjoinpath)->worker_path;
jcpath->innerjoinpath = innerDU->worker_path;
jcpath->outerjoinpath = outerDU->worker_path;
/* TODO update costs of hashjoin, very naife removal of DU cost for now */
/* TODO update costs of hashjoin, very naive removal of DU cost for now */
jcpath->path.startup_cost -= 2000; /* remove the double dist union cost */
jcpath->path.total_cost -= 2000; /* remove the double dist union cost */
@ -928,14 +917,9 @@ OptimizeJoinPath(PlannerInfo *root, Path *originalPath)
return list_make1(newPath);
}
}
default:
{
return NIL;
}
}
}
static List *