5252#include "executor/executor.h"
5353#include "executor/spi.h"
5454#include "nodes/nodeFuncs.h"
55+ #include "optimizer/cost.h"
5556#include "optimizer/planmain.h"
5657#include "optimizer/prep.h"
5758#include "parser/analyze.h"
@@ -88,7 +89,7 @@ static CachedPlan *BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
8889ParamListInfo boundParams );
8990static bool choose_custom_plan (CachedPlanSource * plansource ,
9091ParamListInfo boundParams );
91- static double cached_plan_cost (CachedPlan * plan );
92+ static double cached_plan_cost (CachedPlan * plan , bool include_planner );
9293static void AcquireExecutorLocks (List * stmt_list ,bool acquire );
9394static void AcquirePlannerLocks (List * stmt_list ,bool acquire );
9495static void ScanQueryForLocks (Query * parsetree ,bool acquire );
@@ -998,25 +999,30 @@ choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams)
998999avg_custom_cost = plansource -> total_custom_cost /plansource -> num_custom_plans ;
9991000
10001001/*
1001- * Prefer generic plan if it's less than 10% more expensive than average
1002- * custom plan. This threshold is a bit arbitrary; it'd be better if we
1003- * had some means of comparing planning time to the estimated runtime cost
1004- * differential.
1002+ * Prefer generic plan if it's less expensive than the average custom
1003+ * plan. (Because we include a charge for cost of planning in the
1004+ * custom-plan costs, this means the generic plan only has to be less
1005+ * expensive than the execution cost plus replan cost of the custom
1006+ * plans.)
10051007 *
10061008 * Note that if generic_cost is -1 (indicating we've not yet determined
10071009 * the generic plan cost), we'll always prefer generic at this point.
10081010 */
1009- if (plansource -> generic_cost < avg_custom_cost * 1.1 )
1011+ if (plansource -> generic_cost < avg_custom_cost )
10101012return false;
10111013
10121014return true;
10131015}
10141016
10151017/*
10161018 * cached_plan_cost: calculate estimated cost of a plan
1019+ *
1020+ * If include_planner is true, also include the estimated cost of constructing
1021+ * the plan. (We must factor that into the cost of using a custom plan, but
1022+ * we don't count it for a generic plan.)
10171023 */
10181024static double
1019- cached_plan_cost (CachedPlan * plan )
1025+ cached_plan_cost (CachedPlan * plan , bool include_planner )
10201026{
10211027double result = 0 ;
10221028ListCell * lc ;
@@ -1029,6 +1035,34 @@ cached_plan_cost(CachedPlan *plan)
10291035continue ;/* Ignore utility statements */
10301036
10311037result += plannedstmt -> planTree -> total_cost ;
1038+
1039+ if (include_planner )
1040+ {
1041+ /*
1042+ * Currently we use a very crude estimate of planning effort based
1043+ * on the number of relations in the finished plan's rangetable.
1044+ * Join planning effort actually scales much worse than linearly
1045+ * in the number of relations --- but only until the join collapse
1046+ * limits kick in.Also, while inheritance child relations surely
1047+ * add to planning effort, they don't make the join situation
1048+ * worse. So the actual shape of the planning cost curve versus
1049+ * number of relations isn't all that obvious. It will take
1050+ * considerable work to arrive at a less crude estimate, and for
1051+ * now it's not clear that's worth doing.
1052+ *
1053+ * The other big difficulty here is that we don't have any very
1054+ * good model of how planning cost compares to execution costs.
1055+ * The current multiplier of 1000 * cpu_operator_cost is probably
1056+ * on the low side, but we'll try this for awhile before making a
1057+ * more aggressive correction.
1058+ *
1059+ * If we ever do write a more complicated estimator, it should
1060+ * probably live in src/backend/optimizer/ not here.
1061+ */
1062+ int nrelations = list_length (plannedstmt -> rtable );
1063+
1064+ result += 1000.0 * cpu_operator_cost * (nrelations + 1 );
1065+ }
10321066}
10331067
10341068return result ;
@@ -1104,7 +1138,7 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
11041138MemoryContextGetParent (plansource -> context ));
11051139}
11061140/* Update generic_cost whenever we make a new generic plan */
1107- plansource -> generic_cost = cached_plan_cost (plan );
1141+ plansource -> generic_cost = cached_plan_cost (plan , false );
11081142
11091143/*
11101144 * If, based on the now-known value of generic_cost, we'd not have
@@ -1133,7 +1167,7 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
11331167/* Accumulate total costs of custom plans, but 'ware overflow */
11341168if (plansource -> num_custom_plans < INT_MAX )
11351169{
1136- plansource -> total_custom_cost += cached_plan_cost (plan );
1170+ plansource -> total_custom_cost += cached_plan_cost (plan , true );
11371171plansource -> num_custom_plans ++ ;
11381172}
11391173}