开始

    /** Ready to do the primary planning.*/final_rel = make_one_rel(root, joinlist); 

展开:

/** make_one_rel*      Finds all possible access paths for executing a query, returning a*      single rel that represents the join of all base rels in the query.*/
RelOptInfo *
make_one_rel(PlannerInfo *root, List *joinlist)
{RelOptInfo *rel;Index        rti;/** Construct the all_baserels Relids set.*/root->all_baserels = NULL;for (rti = 1; rti < root->simple_rel_array_size; rti++){RelOptInfo *brel = root->simple_rel_array[rti];/* there may be empty slots corresponding to non-baserel RTEs */if (brel == NULL)continue;Assert(brel->relid == rti);        /* sanity check on array *//* ignore RTEs that are "other rels" */if (brel->reloptkind != RELOPT_BASEREL)continue;root->all_baserels = bms_add_member(root->all_baserels, brel->relid);}/** Generate access paths for the base rels.*/set_base_rel_sizes(root);set_base_rel_pathlists(root);/** Generate access paths for the entire join tree.*/rel = make_rel_from_joinlist(root, joinlist);/** The result should join all and only the query's base rels.*/Assert(bms_equal(rel->relids, root->all_baserels));return rel;
}

其中,

root->all_baserels = bms_add_member(root->all_baserels, brel->relid);

这个展开后可以看到,因为 root->all_baserels 是NULL,所以什么也没执行。

/** bms_add_member - add a specified member to set** Input set is modified or recycled!*/
Bitmapset *
bms_add_member(Bitmapset *a, int x)
{int            wordnum,bitnum;if (x < 0)elog(ERROR, "negative bitmapset member not allowed");if (a == NULL)return bms_make_singleton(x);wordnum = WORDNUM(x);bitnum = BITNUM(x);if (wordnum >= a->nwords){/* Slow path: make a larger set and union the input set into it */Bitmapset  *result;int            nwords;int            i;result = bms_make_singleton(x);nwords = a->nwords;for (i = 0; i < nwords; i++)result->words[i] |= a->words[i];pfree(a);return result;}/* Fast path: x fits in existing set */a->words[wordnum] |= ((bitmapword) 1 << bitnum);return a;
}

接着分析下一个:

set_base_rel_sizes(root);

/** set_base_rel_sizes*      Set the size estimates (rows and widths) for each base-relation entry.** We do this in a separate pass over the base rels so that rowcount* estimates are available for parameterized path generation.*/
static void
set_base_rel_sizes(PlannerInfo *root)
{Index        rti;for (rti = 1; rti < root->simple_rel_array_size; rti++){RelOptInfo *rel = root->simple_rel_array[rti];/* there may be empty slots corresponding to non-baserel RTEs */if (rel == NULL)continue;Assert(rel->relid == rti);        /* sanity check on array *//* ignore RTEs that are "other rels" */if (rel->reloptkind != RELOPT_BASEREL)continue;set_rel_size(root, rel, rti, root->simple_rte_array[rti]);}
}

这是成本评估的非常重要的依据。

再展开  set_rel_size 函数:

/** set_rel_size*      Set size estimates for a base relation*/
static void
set_rel_size(PlannerInfo *root, RelOptInfo *rel,Index rti, RangeTblEntry *rte)
{if (rel->reloptkind == RELOPT_BASEREL &&relation_excluded_by_constraints(root, rel, rte)){/** We proved we don't need to scan the rel via constraint exclusion,* so set up a single dummy path for it.  Here we only check this for* regular baserels; if it's an otherrel, CE was already checked in* set_append_rel_pathlist().** In this case, we go ahead and set up the relation's path right away* instead of leaving it for set_rel_pathlist to do.  This is because* we don't have a convention for marking a rel as dummy except by* assigning a dummy path to it.*/set_dummy_rel_pathlist(rel);}else if (rte->inh){/* It's an "append relation", process accordingly */set_append_rel_size(root, rel, rti, rte);}else{switch (rel->rtekind){case RTE_RELATION:if (rte->relkind == RELKIND_FOREIGN_TABLE){/* Foreign table */set_foreign_size(root, rel, rte);}else{/* Plain relation */set_plain_rel_size(root, rel, rte);}break;case RTE_SUBQUERY:/** Subqueries don't support parameterized paths, so just go* ahead and build their paths immediately.*/set_subquery_pathlist(root, rel, rti, rte);break;case RTE_FUNCTION:set_function_size_estimates(root, rel);break;case RTE_VALUES:set_values_size_estimates(root, rel);break;case RTE_CTE:/** CTEs don't support parameterized paths, so just go ahead* and build their paths immediately.*/if (rte->self_reference)set_worktable_pathlist(root, rel, rte);elseset_cte_pathlist(root, rel, rte);break;default:elog(ERROR, "unexpected rtekind: %d", (int) rel->rtekind);break;}}
}

因为我的是简单查询,所以会走到:

                    /* Plain relation */set_plain_rel_size(root, rel, rte);

展开  set_plain_rel_size :

/** set_plain_rel_size*      Set size estimates for a plain relation (no subquery, no inheritance)*/
static void
set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
{/** Test any partial indexes of rel for applicability.  We must do this* first since partial unique indexes can affect size estimates.*/check_partial_indexes(root, rel);/* Mark rel with estimated output rows, width, etc */set_baserel_size_estimates(root, rel);/** Check to see if we can extract any restriction conditions from join* quals that are OR-of-AND structures.  If so, add them to the rel's* restriction list, and redo the above steps.*/if (create_or_index_quals(root, rel)){check_partial_indexes(root, rel);set_baserel_size_estimates(root, rel);}
}

再对 set_baserel_size_estimates 展开一层:

/** set_baserel_size_estimates*        Set the size estimates for the given base relation.** The rel's targetlist and restrictinfo list must have been constructed* already, and rel->tuples must be set.** We set the following fields of the rel node:*    rows: the estimated number of output tuples (after applying*          restriction clauses).*    width: the estimated average output tuple width in bytes.*    baserestrictcost: estimated cost of evaluating baserestrictinfo clauses.*/
void
set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel)
{double        nrows;/* Should only be applied to base relations */Assert(rel->relid > 0);nrows = rel->tuples *clauselist_selectivity(root,rel->baserestrictinfo,0,JOIN_INNER,NULL);rel->rows = clamp_row_est(nrows);cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root);set_rel_width(root, rel);
}

rel->tuples 值是如何算得?1条记录第表,tuples 是2400, 4条的却是 2140。

得仔细研究。

PostgreSQL在何处处理 sql查询之五十二相关推荐

  1. PostgreSQL在何处处理 sql查询之五十四

    接前面,从 cheapeast_path 的角度,关注 query_planner 函数,对其进行简化: void query_planner(PlannerInfo *root, List *tli ...

  2. PostgreSQL在何处处理 sql查询之十二

    接前面,对 subquery_planner,进行进一步的分析: /*--------------------* subquery_planner* Invokes the planner on a ...

  3. PostgreSQL在何处处理 sql查询之六十二

    对 RelOptInfo * make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2) 函数进行研究: 看看 inner ...

  4. PostgreSQL在何处处理 sql查询之五十一

    继续分析 query_planner: /** query_planner* Generate a path (that is, a simplified plan) for a basic quer ...

  5. PostgreSQL在何处处理 sql查询之四十六

    接前面,再上溯:set_base_rel_pathlists --> set_rel_pathlist /** set_base_rel_pathlists* Finds all paths a ...

  6. PostgreSQL在何处处理 sql查询之三十九

    接前面,这次重点分析 ExecScan: 其for 循环内部: for (;;){ TupleTableSlot *slot;CHECK_FOR_INTERRUPTS(); slot = ExecSc ...

  7. PostgreSQL在何处处理 sql查询之三十八

    这里又遇到了函数指针: executor.h头文件中,定义了 ExecScanAccessMtd 指针,或者定义了一个ExecScanAccessMtd 函数原型的指针 /** prototypes ...

  8. PostgreSQL在何处处理 sql查询之六十六

    继续分析 /** final_cost_hashjoin* Final estimate of the cost and result size of a hashjoin path.** Note: ...

  9. 第九章 SQL查询数据库(二)

    文章目录 第九章 SQL查询数据库(二) 调用用户定义函数的查询 查询串行对象属性 查询集合 使用说明和限制 调用文本搜索的查询 伪字段 查询元数据 快速查询 查询和企业缓存协议Enterprise ...

最新文章

  1. linux驱动开发字符设备,linux驱动开发(三) 字符设备驱动框架
  2. SAP评估控制 Valuation control
  3. 及时沟通的重要性_沟通与代码同样重要
  4. 第六十二期:腾讯云发布“小程序·云开发十大优秀实践”:猫眼、唯品会等入选
  5. 掌控谈话~谈价格的秘诀
  6. python爬取百度文库_利用Python语言轻松爬取数据
  7. java后端简历项目经历_为了面试字节跳动后端开发岗(Java)鬼知道我经历了什么.....
  8. php autoload 性能,PHP __autoload()方法真的影响性能吗?
  9. Barrage 弹幕实现原理
  10. Access2016学习2
  11. 软件著作权申请文档模版
  12. matlab随机线性微分方程,基于MATLAB的随机线性微分方程的求解
  13. 运行caffe代码 SegNet
  14. java .getbytes_java中String的getBytes方法使用
  15. wangEditor富文本实现导入word功能
  16. JETT(五)-支持Excel公式
  17. 为什么别人可以年薪百万?
  18. 开手游要选用怎么样的服务器
  19. android加密、签名相关
  20. linux C读取字库文件

热门文章

  1. doe报告模板_技术漫谈|关于制剂研发过程中的实验设计(DOE)误区讨论
  2. drcom linux怎么运行,drcom for linux
  3. java gui 选项_【Java-GUI】04 菜单
  4. java线程能做什么_java中的多线程能做什么 ?基本作用能说下吗?
  5. 你知道吗?脑机接口训练会对大脑物质结构和功能产生影响
  6. 脑源(brainsourcing)技术可以自动识别人类的偏好
  7. 量子信息之父辞世,开山论文写完14年才被发表,晚年去当建筑工人
  8. 用GAN创造新蛋白只需几周,大幅缩短制药周期 | Nature子刊
  9. 谷歌甲骨文Java专利大战终审判决:安卓使用Java不构成侵权
  10. MIT喊你来上课,深度学习课程,免费的那种 | 资源