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,
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 DeferredErrorMessage * DeferErrorIfPartitionTableNotSingleReplicated(Oid
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
* 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 "
"local table"),
@ -183,13 +184,27 @@ distributed_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
* 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
* distributed query.
*
* Since fast-path queries do not through standard planner, we skip unnecessary
* parts in that case.
*/
rteIdCounter = AssignRTEIdentities(rangeTableList, rteIdCounter);
originalQuery = copyObject(parse);
if (!fastPathRouterQuery)
{
rteIdCounter = AssignRTEIdentities(rangeTableList, rteIdCounter);
originalQuery = copyObject(parse);
setPartitionedTablesInherited = false;
AdjustPartitioningForDistributedPlanning(rangeTableList,
setPartitionedTablesInherited);
setPartitionedTablesInherited = false;
AdjustPartitioningForDistributedPlanning(rangeTableList,
setPartitionedTablesInherited);
}
else
{
/*
* We still need to copy the parse tree because the FastPathPlanner
* modifies it.
*/
originalQuery = copyObject(parse);
}
}
/*
@ -249,9 +264,12 @@ distributed_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result = CreateDistributedPlannedStmt(planId, result, originalQuery, parse,
boundParams, plannerRestrictionContext);
setPartitionedTablesInherited = true;
AdjustPartitioningForDistributedPlanning(rangeTableList,
setPartitionedTablesInherited);
if (!fastPathRouterQuery)
{
setPartitionedTablesInherited = true;
AdjustPartitioningForDistributedPlanning(rangeTableList,
setPartitionedTablesInherited);
}
}
else
{
@ -667,7 +685,8 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
{
DistributedPlan *distributedPlan = NULL;
bool hasCtes = originalQuery->cteList != NIL;
bool fastPathRouterQuery =
plannerRestrictionContext->fastPathRestrictionContext->fastPathRouterQuery;
if (IsModifyCommand(originalQuery))
{
@ -703,7 +722,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
if (distributedPlan->planningError == NULL)
{
FinalizeDistributedPlan(distributedPlan, originalQuery);
FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan;
}
@ -725,7 +744,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
plannerRestrictionContext);
if (distributedPlan->planningError == NULL)
{
FinalizeDistributedPlan(distributedPlan, originalQuery);
FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan;
}
@ -819,7 +838,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
plannerRestrictionContext);
distributedPlan->subPlanList = subPlanList;
FinalizeDistributedPlan(distributedPlan, originalQuery);
FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan;
}
@ -831,7 +850,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
*/
if (IsModifyCommand(originalQuery))
{
FinalizeDistributedPlan(distributedPlan, originalQuery);
FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan;
}
@ -864,7 +883,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
/* distributed plan currently should always succeed or error out */
Assert(distributedPlan && distributedPlan->planningError == NULL);
FinalizeDistributedPlan(distributedPlan, originalQuery);
FinalizeDistributedPlan(distributedPlan, originalQuery, fastPathRouterQuery);
return distributedPlan;
}
@ -875,9 +894,17 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
* currently only implements some optimizations for intermediate result(s) pruning.
*/
static void
FinalizeDistributedPlan(DistributedPlan *plan, Query *originalQuery)
FinalizeDistributedPlan(DistributedPlan *plan, Query *originalQuery,
bool fastPathRouterQuery)
{
RecordSubPlansUsedInPlan(plan, originalQuery);
/*
* Fast path queries, we cannot have any subplans by their definition,
* so skip expensive traversals.
*/
if (!fastPathRouterQuery)
{
RecordSubPlansUsedInPlan(plan, originalQuery);
}
}

View File

@ -552,6 +552,8 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
ListCell *rangeTableCell = NULL;
uint32 queryTableCount = 0;
CmdType commandType = queryTree->commandType;
bool fastPathRouterQuery =
plannerRestrictionContext->fastPathRestrictionContext->fastPathRouterQuery;
Oid distributedTableId = ModifyQueryResultRelationId(queryTree);
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
* the rows could be changed before the modification part of
* 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);
if (hasTidColumn)
@ -649,8 +655,15 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
}
}
/* extract range table entries */
ExtractRangeTableEntryWalker((Node *) originalQuery, &rangeTableList);
/*
* 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);
}
foreach(rangeTableCell, rangeTableList)
{