PostgreSQL在何处处理 sql查询之十四
Path莫非指的就是 物理访问路径?
/* * query_planner * Generate a path (that is, a simplified plan) for a basic query, * which may involve joins but not any fancier features. * * Since query_planner does not handle the toplevel processing (grouping, * sorting, etc) it cannot select the best path by itself. It selects * two paths: the cheapest path that produces all the required tuples, * independent of any ordering considerations, and the cheapest path that * produces the expected fraction of the required tuples in the required * ordering, if there is a path that is cheaper for this than just sorting * the output of the cheapest overall path. The caller (grouping_planner) * will make the final decision about which to use. * * Input parameters: * root describes the query to plan * tlist is the target list the query should produce * (this is NOT necessarily root->parse->targetList!) * tuple_fraction is the fraction of tuples we expect will be retrieved * limit_tuples is a hard limit on number of tuples to retrieve, * or -1 if no limit * * Output parameters: * *cheapest_path receives the overall-cheapest path for the query * *sorted_path receives the cheapest presorted path for the query, * if any (NULL if there is no useful presorted path) * *num_groups receives the estimated number of groups, or 1 if query * does not use grouping * * Note: the PlannerInfo node also includes a query_pathkeys field, which is * both an input and an output of query_planner(). The input value signals * query_planner that the indicated sort order is wanted in the final output * plan. But this value has not yet been "canonicalized", since the needed * info does not get computed until we scan the qual clauses. We canonicalize * it as soon as that task is done. (The main reason query_pathkeys is a * PlannerInfo field and not a passed parameter is that the low-level routines * in indxpath.c need to see it.) * * Note: the PlannerInfo node includes other pathkeys fields besides * query_pathkeys, all of which need to be canonicalized once the info is * available. See canonicalize_all_pathkeys. * * tuple_fraction is interpreted as follows: * 0: expect all tuples to be retrieved (normal case) * 0 < tuple_fraction < 1: expect the given fraction of tuples available * from the plan to be retrieved * tuple_fraction >= 1: tuple_fraction is the absolute number of tuples * expected to be retrieved (ie, a LIMIT specification) * Note that a nonzero tuple_fraction could come from outer context; it is * therefore not redundant with limit_tuples. We use limit_tuples to determine * whether a bounded sort can be used at runtime. */ void query_planner(PlannerInfo *root, List *tlist, double tuple_fraction, double limit_tuples, Path **cheapest_path, Path **sorted_path, double *num_groups) { ... /* * Construct RelOptInfo nodes for all base relations in query, and * indirectly for all appendrel member relations ("other rels"). This * will give us a RelOptInfo for every "simple" (non-join) rel involved in * the query. * * Note: the reason we find the rels by searching the jointree and * appendrel list, rather than just scanning the rangetable, is that the * rangetable may contain RTEs for rels not actively part of the query, * for example views. We don't want to make RelOptInfos for them. */ add_base_rels_to_query(root, (Node *) parse->jointree); /* * Examine the targetlist and join tree, adding entries to baserel * targetlists for all referenced Vars, and generating PlaceHolderInfo * entries for all referenced PlaceHolderVars. Restrict and join clauses * are added to appropriate lists belonging to the mentioned relations. We * also build EquivalenceClasses for provably equivalent expressions. The * SpecialJoinInfo list is also built to hold information about join order * restrictions. Finally, we form a target joinlist for make_one_rel() to * work from. */ build_base_rel_tlists(root, tlist); find_placeholders_in_jointree(root); joinlist = deconstruct_jointree(root); ... }
物理访问,发生在 add_base_rels_to_query 内部