From 13a9b55695fdb40d7b777bf12c59da00ac9a2fa1 Mon Sep 17 00:00:00 2001 From: Onder Kalaci Date: Thu, 19 Dec 2019 15:16:58 +0100 Subject: [PATCH] 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. --- .../distributed/planner/distributed_planner.c | 63 +++++++++++++------ .../planner/multi_router_planner.c | 19 +++++- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/backend/distributed/planner/distributed_planner.c b/src/backend/distributed/planner/distributed_planner.c index ce45416e5..ff9305010 100644 --- a/src/backend/distributed/planner/distributed_planner.c +++ b/src/backend/distributed/planner/distributed_planner.c @@ -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); + } } diff --git a/src/backend/distributed/planner/multi_router_planner.c b/src/backend/distributed/planner/multi_router_planner.c index 99d884a65..26d4c2438 100644 --- a/src/backend/distributed/planner/multi_router_planner.c +++ b/src/backend/distributed/planner/multi_router_planner.c @@ -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) {