文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PostgreSQL中query_planner函数处理逻辑是怎样的

2024-04-02 19:55

关注

这篇文章主要讲解了“PostgreSQL中query_planner函数处理逻辑是怎样的”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL中query_planner函数处理逻辑是怎样的”吧!

一、重要的数据结构

在query_planner中,对root(PlannerInfo)结构进行初始化和处理,为后续的计划作准备.
PlannerInfo

 
 struct AppendRelInfo;
 
 typedef struct PlannerInfo
 {
     NodeTag     type;//Node标识
 
     Query      *parse;          
 
     PlannerGlobal *glob;        
 
     Index       query_level;    
 
     struct PlannerInfo *parent_root;    
 
     
     List       *plan_params;    
     Bitmapset  *outer_params;
 
     
     
     struct RelOptInfo **simple_rel_array;   
     int         simple_rel_array_size;  
 
     
     RangeTblEntry **simple_rte_array;   
 
     
     struct AppendRelInfo **append_rel_array;//先前已介绍,在处理集合操作如UNION ALL时使用
 
     
     Relids      all_baserels;//"base rels"
 
     
     Relids      nullable_baserels;//Nullable-side端的"base rels"
 
     
     List       *join_rel_list;  
     struct HTAB *join_rel_hash; 
 
     
     List      **join_rel_level; 
     int         join_cur_level; 
 
     List       *init_plans;     
 
     List       *cte_plan_ids;   
 
     List       *multiexpr_params;   
 
     List       *eq_classes;     
 
     List       *canon_pathkeys; 
 
     List       *left_join_clauses;  
 
     List       *right_join_clauses; 
 
     List       *full_join_clauses;  
 
     List       *join_info_list; 
 
     List       *append_rel_list;    
 
     List       *rowMarks;       
 
     List       *placeholder_list;   
 
     List       *fkey_list;      
 
     List       *query_pathkeys; 
 
     List       *group_pathkeys; 
     List       *window_pathkeys;    
     List       *distinct_pathkeys;  
     List       *sort_pathkeys;  
 
     List       *part_schemes;   
 
     List       *initial_rels;   
 
     
     List       *upper_rels[UPPERREL_FINAL + 1]; 
 
     
     struct PathTarget *upper_targets[UPPERREL_FINAL + 1];//
 
     
     List       *processed_tlist;//最后需处理的投影列
 
     
     AttrNumber *grouping_map;   
     List       *minmax_aggs;    
 
     MemoryContext planner_cxt;  
 
     double      total_table_pages;  
 
     double      tuple_fraction; 
     double      limit_tuples;   
 
     Index       qual_security_level;    
     
 
     InheritanceKind inhTargetKind;  
     bool        hasJoinRTEs;    
     bool        hasLateralRTEs; 
     bool        hasDeletedRTEs; 
     bool        hasHavingQual;  
     bool        hasPseudoConstantQuals; 
     bool        hasRecursion;   
 
     
     int         wt_param_id;    
     struct Path *non_recursive_path;    
 
     
     Relids      curOuterRels;   
     List       *curOuterParams; 
 
     
     void       *join_search_private;
 
     
     bool        partColsUpdated;
 } PlannerInfo;

二、源码解读

本节介绍query_planner的主流程以及setup_simple_rel_arrays和setup_append_rel_array两个子函数的实现逻辑.
query_planner

 
 RelOptInfo *
 query_planner(PlannerInfo *root, List *tlist,
               query_pathkeys_callback qp_callback, void *qp_extra)
 {
     Query      *parse = root->parse;//查询树
     List       *joinlist;
     RelOptInfo *final_rel;//结果
     Index       rti;//RTE的index
     double      total_pages;//总pages数
 
     
     if (parse->jointree->fromlist == NIL)//简单SQL,无FROM/WHERE语句
     {
         
         final_rel = build_empty_join_rel(root);//创建返回结果
 
         
         if (root->glob->parallelModeOK)//并行模式?
             final_rel->consider_parallel =
                 is_parallel_safe(root, parse->jointree->quals);
 
         
         add_path(final_rel, (Path *)
                  create_result_path(root, final_rel,
                                     final_rel->reltarget,
                                     (List *) parse->jointree->quals));//添加访问路径
 
         
         set_cheapest(final_rel);//选择最优的访问路径
 
         
         root->canon_pathkeys = NIL;
         (*qp_callback) (root, qp_extra);//回调函数
 
         return final_rel;//返回
     }
 
 
     
     root->join_rel_list = NIL;//初始化PlannerInfo
     root->join_rel_hash = NULL;
     root->join_rel_level = NULL;
     root->join_cur_level = 0;
     root->canon_pathkeys = NIL;
     root->left_join_clauses = NIL;
     root->right_join_clauses = NIL;
     root->full_join_clauses = NIL;
     root->join_info_list = NIL;
     root->placeholder_list = NIL;
     root->fkey_list = NIL;
     root->initial_rels = NIL;
 
     
     setup_simple_rel_arrays(root);//初始化PlannerInfo->simple_rel/rte_array&size
 
     
     setup_append_rel_array(root);//初始化PlannerInfo->append_rel_array(通过append_rel_list)
 
     
     add_base_rels_to_query(root, (Node *) parse->jointree);//构建RelOptInfo节点
 
     
     build_base_rel_tlists(root, tlist);//构建"base rels"的投影列
 
     find_placeholders_in_jointree(root);//处理jointree中的PHI
 
     find_lateral_references(root);//处理jointree中Lateral依赖
 
     joinlist = deconstruct_jointree(root);//重构jointree
 
     
     reconsider_outer_join_clauses(root);//已创建等价类,那么需要重新考虑被推后处理的外连接表达式
 
     
     generate_base_implied_equalities(root);//等价类构建后,生成因此外加的约束语句
 
     
     (*qp_callback) (root, qp_extra);//调用回调函数
 
     
     fix_placeholder_input_needed_levels(root);//检查在子查询上拉时生成的PH表达式,确保Vars是OK的
 
     
     joinlist = remove_useless_joins(root, joinlist);//清除无用的外连接
 
     
     reduce_unique_semijoins(root);//消除半连接
 
     
     add_placeholders_to_base_rels(root);//在"base rels"中添加PH
 
     
     create_lateral_join_info(root);//创建Lateral连接信息
 
     
     match_foreign_keys_to_quals(root);//匹配外键信息
 
     
     extract_restriction_or_clauses(root);//在OR语句中抽取约束条件
 
     
     total_pages = 0;
     for (rti = 1; rti < root->simple_rel_array_size; rti++)//计算总pages
     {
         RelOptInfo *brel = root->simple_rel_array[rti];
 
         if (brel == NULL)
             continue;
 
         Assert(brel->relid == rti); 
 
         if (IS_SIMPLE_REL(brel))
             total_pages += (double) brel->pages;
     }
     root->total_table_pages = total_pages;//赋值
 
     
     final_rel = make_one_rel(root, joinlist);//执行主要的计划过程
 
     
     if (!final_rel || !final_rel->cheapest_total_path ||
         final_rel->cheapest_total_path->param_info != NULL)
         elog(ERROR, "failed to construct the join relation");//检查
 
     return final_rel;//返回结果
 }

setup_simple_rel_arrays
初始化setup_simple_rel_arrays(注意:[0]无用)和setup_simple_rel_arrays

 
 void
 setup_simple_rel_arrays(PlannerInfo *root)
 {
     Index       rti;
     ListCell   *lc;
 
     
     root->simple_rel_array_size = list_length(root->parse->rtable) + 1;
 
     
     root->simple_rel_array = (RelOptInfo **)
         palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *));
 
     
     root->simple_rte_array = (RangeTblEntry **)
         palloc0(root->simple_rel_array_size * sizeof(RangeTblEntry *));
     rti = 1;
     foreach(lc, root->parse->rtable)
     {
         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
 
         root->simple_rte_array[rti++] = rte;
     }
 }

setup_append_rel_array
源码比较简单,读取append_rel_list中的信息初始化append_rel_array

 
 void
 setup_append_rel_array(PlannerInfo *root)
 {
     ListCell   *lc;
     int         size = list_length(root->parse->rtable) + 1;
 
     if (root->append_rel_list == NIL)
     {
         root->append_rel_array = NULL;
         return;
     }
 
     root->append_rel_array = (AppendRelInfo **)
         palloc0(size * sizeof(AppendRelInfo *));
 
     foreach(lc, root->append_rel_list)
     {
         AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
         int         child_relid = appinfo->child_relid;
 
         
         Assert(child_relid < size);
 
         if (root->append_rel_array[child_relid])
             elog(ERROR, "child relation already exists");
 
         root->append_rel_array[child_relid] = appinfo;
     }
 }

感谢各位的阅读,以上就是“PostgreSQL中query_planner函数处理逻辑是怎样的”的内容了,经过本文的学习后,相信大家对PostgreSQL中query_planner函数处理逻辑是怎样的这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯