接前面。
从 cheapest_total_path 来看:
query_planner 会先调用 build_simple_rel,这里完成了 cheapest_total_path 的初始化。
(query_planner --> add_base_rels_to_query --> query_planner)
然后,query_planner 再在后面调用 create_plan,最终设置 plan_rows。
那么,是在何处 设置了 cheapest_total_path 的值呢?
经过查找,看到了如下的调用关系:
make_one_rel--> set_base_rel_pathlists --> set_rel_pathlist --> set_plain_rel_pathlist--> set_cheapest
先看 set_cheapest:
/* * set_cheapest * Find the minimum-cost paths from among a relation's paths, * and save them in the rel's cheapest-path fields. * * Only unparameterized paths are considered candidates for cheapest_startup * and cheapest_total. The cheapest_parameterized_paths list collects paths * that are cheapest-total for their parameterization (i.e., there is no * cheaper path with the same or weaker parameterization). This list always * includes the unparameterized cheapest-total path, too. * * This is normally called only after we've finished constructing the path * list for the rel node. */ void set_cheapest(RelOptInfo *parent_rel) { fprintf(stderr,"In set_cheapest ........\n"); Path *cheapest_startup_path; Path *cheapest_total_path; bool have_parameterized_paths; ListCell *p; Assert(IsA(parent_rel, RelOptInfo)); cheapest_startup_path = cheapest_total_path = NULL; have_parameterized_paths = false; foreach(p, parent_rel->pathlist) { Path *path = (Path *) lfirst(p); int cmp; /* We only consider unparameterized paths in this step */ if (path->param_info) { have_parameterized_paths = true; continue; } if (cheapest_total_path == NULL) { cheapest_startup_path = cheapest_total_path = path; continue; } /* * If we find two paths of identical costs, try to keep the * better-sorted one. The paths might have unrelated sort orderings, * in which case we can only guess which might be better to keep, but * if one is superior then we definitely should keep that one. */ cmp = compare_path_costs(cheapest_startup_path, path, STARTUP_COST); if (cmp > 0 || (cmp == 0 && compare_pathkeys(cheapest_startup_path->pathkeys, path->pathkeys) == PATHKEYS_BETTER2)) cheapest_startup_path = path; cmp = compare_path_costs(cheapest_total_path, path, TOTAL_COST); if (cmp > 0 || (cmp == 0 && compare_pathkeys(cheapest_total_path->pathkeys, path->pathkeys) == PATHKEYS_BETTER2)) cheapest_total_path = path; } if (cheapest_total_path == NULL) elog(ERROR, "could not devise a query plan for the given query"); parent_rel->cheapest_startup_path = cheapest_startup_path; parent_rel->cheapest_total_path = cheapest_total_path; parent_rel->cheapest_unique_path = NULL; /* computed only if needed */ /* Seed the parameterized-paths list with the cheapest total */ parent_rel->cheapest_parameterized_paths = list_make1(cheapest_total_path); /* And, if there are any parameterized paths, add them in one at a time */ if (have_parameterized_paths) { foreach(p, parent_rel->pathlist) { Path *path = (Path *) lfirst(p); if (path->param_info) add_parameterized_path(parent_rel, path); } } }