Skip expensive checks when fast-path query

The definition of fast-path query is very strict. So, we don't need
to do some extra checks.
pull/3332/head
Onder Kalaci 2019-12-19 15:16:58 +01:00 committed by Jelte Fennema
parent 7f3ab7892d
commit 13a9b55695
2 changed files with 61 additions and 21 deletions

View File

@ -79,7 +79,8 @@ static DistributedPlan * CreateDistributedPlan(uint64 planId, Query *originalQue
bool hasUnresolvedParams, bool hasUnresolvedParams,
PlannerRestrictionContext * PlannerRestrictionContext *
plannerRestrictionContext); plannerRestrictionContext);
static void FinalizeDistributedPlan(DistributedPlan *plan, Query *originalQuery); static void FinalizeDistributedPlan(DistributedPlan *plan, Query *originalQuery,
bool fastPathRouterQuery);
static void RecordSubPlansUsedInPlan(DistributedPlan *plan, Query *originalQuery); static void RecordSubPlansUsedInPlan(DistributedPlan *plan, Query *originalQuery);
static DeferredErrorMessage * DeferErrorIfPartitionTableNotSingleReplicated(Oid static DeferredErrorMessage * DeferErrorIfPartitionTableNotSingleReplicated(Oid
relationId); relationId);
@ -168,7 +169,7 @@ distributed_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
* don't have a way of doing both things and therefore error out, but do * don't have a way of doing both things and therefore error out, but do
* have a handy tip for users. * have a handy tip for users.
*/ */
if (InsertSelectIntoLocalTable(parse)) if (!fastPathRouterQuery && InsertSelectIntoLocalTable(parse))
{ {
ereport(ERROR, (errmsg("cannot INSERT rows from a distributed query into a " ereport(ERROR, (errmsg("cannot INSERT rows from a distributed query into a "
"local table"), "local table"),
@ -183,7 +184,12 @@ distributed_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
* set, which doesn't break our goals, but, prevents us keeping an extra copy * set, which doesn't break our goals, but, prevents us keeping an extra copy
* of the query tree. Note that we copy the query tree once we're sure it's a * of the query tree. Note that we copy the query tree once we're sure it's a
* distributed query. * distributed query.
*
* Since fast-path queries do not through standard planner, we skip unnecessary
* parts in that case.
*/ */
if (!fastPathRouterQuery)
{
rteIdCounter = AssignRTEIdentities(rangeTableList, rteIdCounter); rteIdCounter = AssignRTEIdentities(rangeTableList, rteIdCounter);
originalQuery = copyObject(parse); originalQuery = copyObject(parse);
@ -191,6 +197,15 @@ distributed_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
AdjustPartitioningForDistributedPlanning(rangeTableList, AdjustPartitioningForDistributedPlanning(rangeTableList,
setPartitionedTablesInherited); setPartitionedTablesInherited);
} }
else
{
/*
* We still need to copy the parse tree because the FastPathPlanner
* modifies it.
*/
originalQuery = copyObject(parse);
}
}
/* /*
* Make sure that we hide shard names on the Citus MX worker nodes. See comments in * Make sure that we hide shard names on the Citus MX worker nodes. See comments in
@ -249,10 +264,13 @@ distributed_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result = CreateDistributedPlannedStmt(planId, result, originalQuery, parse, result = CreateDistributedPlannedStmt(planId, result, originalQuery, parse,
boundParams, plannerRestrictionContext); boundParams, plannerRestrictionContext);
if (!fastPathRouterQuery)
{
setPartitionedTablesInherited = true; setPartitionedTablesInherited = true;
AdjustPartitioningForDistributedPlanning(rangeTableList, AdjustPartitioningForDistributedPlanning(rangeTableList,
setPartitionedTablesInherited); setPartitionedTablesInherited);
} }
}
else else
{ {
bool hasExternParam = false; bool hasExternParam = false;
@ -667,7 +685,8 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
{ {
DistributedPlan *distributedPlan = NULL; DistributedPlan *distributedPlan = NULL;
bool hasCtes = originalQuery->cteList != NIL; bool hasCtes = originalQuery->cteList != NIL;
bool fastPathRouterQuery =
plannerRestrictionContext->fastPathRestrictionContext->fastPathRouterQuery;
if (IsModifyCommand(originalQuery)) if (IsModifyCommand(originalQuery))
{ {
@ -703,7 +722,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
if (distributedPlan->planningError == NULL) if (distributedPlan->planningError == NULL)
{ {
FinalizeDistributedPlan(distributedPlan, originalQuery); FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan; return distributedPlan;
} }
@ -725,7 +744,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
plannerRestrictionContext); plannerRestrictionContext);
if (distributedPlan->planningError == NULL) if (distributedPlan->planningError == NULL)
{ {
FinalizeDistributedPlan(distributedPlan, originalQuery); FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan; return distributedPlan;
} }
@ -819,7 +838,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
plannerRestrictionContext); plannerRestrictionContext);
distributedPlan->subPlanList = subPlanList; distributedPlan->subPlanList = subPlanList;
FinalizeDistributedPlan(distributedPlan, originalQuery); FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan; return distributedPlan;
} }
@ -831,7 +850,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
*/ */
if (IsModifyCommand(originalQuery)) if (IsModifyCommand(originalQuery))
{ {
FinalizeDistributedPlan(distributedPlan, originalQuery); FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan; return distributedPlan;
} }
@ -864,7 +883,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
/* distributed plan currently should always succeed or error out */ /* distributed plan currently should always succeed or error out */
Assert(distributedPlan && distributedPlan->planningError == NULL); Assert(distributedPlan && distributedPlan->planningError == NULL);
FinalizeDistributedPlan(distributedPlan, originalQuery); FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan; return distributedPlan;
} }
@ -875,10 +894,18 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
* currently only implements some optimizations for intermediate result(s) pruning. * currently only implements some optimizations for intermediate result(s) pruning.
*/ */
static void static void
FinalizeDistributedPlan(DistributedPlan *plan, Query *originalQuery) FinalizeDistributedPlan(DistributedPlan *plan, Query *originalQuery,
bool fastPathRouterQuery)
{
/*
* Fast path queries, we cannot have any subplans by their definition,
* so skip expensive traversals.
*/
if (!fastPathRouterQuery)
{ {
RecordSubPlansUsedInPlan(plan, originalQuery); RecordSubPlansUsedInPlan(plan, originalQuery);
} }
}
/* /*

View File

@ -552,6 +552,8 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
ListCell *rangeTableCell = NULL; ListCell *rangeTableCell = NULL;
uint32 queryTableCount = 0; uint32 queryTableCount = 0;
CmdType commandType = queryTree->commandType; CmdType commandType = queryTree->commandType;
bool fastPathRouterQuery =
plannerRestrictionContext->fastPathRestrictionContext->fastPathRouterQuery;
Oid distributedTableId = ModifyQueryResultRelationId(queryTree); Oid distributedTableId = ModifyQueryResultRelationId(queryTree);
if (!IsDistributedTable(distributedTableId)) if (!IsDistributedTable(distributedTableId))
@ -575,8 +577,12 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
* rows based on the ctid column. This is a bad idea because ctid of * rows based on the ctid column. This is a bad idea because ctid of
* the rows could be changed before the modification part of * the rows could be changed before the modification part of
* the query is executed. * the query is executed.
*
* We can exclude fast path queries since they cannot have intermediate
* results by definition.
*/ */
if (ContainsReadIntermediateResultFunction((Node *) originalQuery)) if (!fastPathRouterQuery &&
ContainsReadIntermediateResultFunction((Node *) originalQuery))
{ {
bool hasTidColumn = FindNodeCheck((Node *) originalQuery->jointree, IsTidColumn); bool hasTidColumn = FindNodeCheck((Node *) originalQuery->jointree, IsTidColumn);
if (hasTidColumn) if (hasTidColumn)
@ -649,8 +655,15 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
} }
} }
/* extract range table entries */ /*
* Extract range table entries for queries that are not fast path. We can skip fast
* path queries because their definition is a single RTE entry, which is a relation,
* so the following check doesn't apply for fast-path queries.
*/
if (!fastPathRouterQuery)
{
ExtractRangeTableEntryWalker((Node *) originalQuery, &rangeTableList); ExtractRangeTableEntryWalker((Node *) originalQuery, &rangeTableList);
}
foreach(rangeTableCell, rangeTableList) foreach(rangeTableCell, rangeTableList)
{ {