您的位置:首页 > 其它

对get_baserel_parampathinfo函数的学习

2013-06-19 14:49 387 查看
/*
* get_baserel_parampathinfo
*        Get the ParamPathInfo for a parameterized path for a base relation,
*        constructing one if we don't have one already.
*
* This centralizes estimating the rowcounts for parameterized paths.
* We need to cache those to be sure we use the same rowcount for all paths
* of the same parameterization for a given rel.  This is also a convenient
* place to determine which movable join clauses the parameterized path will
* be responsible for evaluating.
*/
ParamPathInfo *
get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
Relids required_outer)
{
ParamPathInfo *ppi;
Relids        joinrelids;
List       *pclauses;
double        rows;
ListCell   *lc;

/* Unparameterized paths have no ParamPathInfo */
if (bms_is_empty(required_outer))
return NULL;

Assert(!bms_overlap(baserel->relids, required_outer));

/* If we already have a PPI for this parameterization, just return it */
foreach(lc, baserel->ppilist)
{
ppi = (ParamPathInfo *) lfirst(lc);
if (bms_equal(ppi->ppi_req_outer, required_outer))
return ppi;
}

/*
* Identify all joinclauses that are movable to this base rel given this
* parameterization.
*/
joinrelids = bms_union(baserel->relids, required_outer);
pclauses = NIL;
foreach(lc, baserel->joininfo)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);

if (join_clause_is_movable_into(rinfo,
baserel->relids,
joinrelids))
pclauses = lappend(pclauses, rinfo);
}

/*
* Add in joinclauses generated by EquivalenceClasses, too.  (These
* necessarily satisfy join_clause_is_movable_into.)
*/
pclauses = list_concat(pclauses,
generate_join_implied_equalities(root,
joinrelids,
required_outer,
baserel));

/* Estimate the number of rows returned by the parameterized scan */
rows = get_parameterized_baserel_size(root, baserel, pclauses);

/* And now we can build the ParamPathInfo */
ppi = makeNode(ParamPathInfo);
ppi->ppi_req_outer = required_outer;
ppi->ppi_rows = rows;
ppi->ppi_clauses = pclauses;
baserel->ppilist = lappend(baserel->ppilist, ppi);

return ppi;
}


上溯来看:

/*
* set_plain_rel_pathlist
*      Build access paths for a plain relation (no subquery, no inheritance)
*/
static void
set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
{
/* Consider sequential scan */
add_path(rel, create_seqscan_path(root, rel, NULL));

/* Consider index scans */
create_index_paths(root, rel);

/* Consider TID scans */
create_tidscan_paths(root, rel);

/* Now find the cheapest of the paths for this rel */
set_cheapest(rel);
}


只要进入了 set_plain_rel_pathlist 函数,进行

add_path(rel, create_seqscan_path(root, rel, NULL))调用是,给予 create_seqscan_path 的第三个参数是NULL

再看 create_seqscan_path:

/*
* create_seqscan_path
*      Creates a path corresponding to a sequential scan, returning the
*      pathnode.
*/
Path *
create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
{
Path       *pathnode = makeNode(Path);

pathnode->pathtype = T_SeqScan;
pathnode->parent = rel;
pathnode->param_info = get_baserel_parampathinfo(root, rel,
required_outer);

pathnode->pathkeys = NIL;    /* seqscan has unordered result */

cost_seqscan(pathnode, root, rel, pathnode->param_info);

return pathnode;
}


看这句话:pathnode->param_info = get_baserel_parampathinfo(root, rel, required_outer);

由于传递的required_outer是NULL,所以就是 get_baserel_parampathinfo(root, rel, NULL);

那么:

/*
* get_baserel_parampathinfo
*        Get the ParamPathInfo for a parameterized path for a base relation,
*        constructing one if we don't have one already.
*
* This centralizes estimating the rowcounts for parameterized paths.
* We need to cache those to be sure we use the same rowcount for all paths
* of the same parameterization for a given rel.  This is also a convenient
* place to determine which movable join clauses the parameterized path will
* be responsible for evaluating.
*/
ParamPathInfo *
get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
Relids required_outer)
{
ParamPathInfo *ppi;
Relids        joinrelids;
List       *pclauses;
double        rows;
ListCell   *lc;

/* Unparameterized paths have no ParamPathInfo */
if (bms_is_empty(required_outer))
return NULL;

Assert(!bms_overlap(baserel->relids, required_outer));

/* If we already have a PPI for this parameterization, just return it */
foreach(lc, baserel->ppilist)
{
ppi = (ParamPathInfo *) lfirst(lc);
if (bms_equal(ppi->ppi_req_outer, required_outer))
return ppi;
}

/*
* Identify all joinclauses that are movable to this base rel given this
* parameterization.
*/
joinrelids = bms_union(baserel->relids, required_outer);
pclauses = NIL;
foreach(lc, baserel->joininfo)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);

if (join_clause_is_movable_into(rinfo,
baserel->relids,
joinrelids))
pclauses = lappend(pclauses, rinfo);
}

/*
* Add in joinclauses generated by EquivalenceClasses, too.  (These
* necessarily satisfy join_clause_is_movable_into.)
*/
pclauses = list_concat(pclauses,
generate_join_implied_equalities(root,
joinrelids,
required_outer,
baserel));

/* Estimate the number of rows returned by the parameterized scan */
rows = get_parameterized_baserel_size(root, baserel, pclauses);

/* And now we can build the ParamPathInfo */
ppi = makeNode(ParamPathInfo);
ppi->ppi_req_outer = required_outer;
ppi->ppi_rows = rows;
ppi->ppi_clauses = pclauses;
baserel->ppilist = lappend(baserel->ppilist, ppi);

return ppi;
}


看这一小段:

/* Unparameterized paths have no ParamPathInfo */
if (bms_is_empty(required_outer))
return NULL;


看看 bms_is_empty:

/*
* bms_is_empty - is a set empty?
*
* This is even faster than bms_membership().
*/
bool
bms_is_empty(const Bitmapset *a)
{
int            nwords;
int            wordnum;

if (a == NULL)
return true;

nwords = a->nwords;
for (wordnum = 0; wordnum < nwords; wordnum++)
{
bitmapword    w = a->words[wordnum];

if (w != 0)
return false;
}
return true;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐