• 对get_baserel_parampathinfo函数的学习


    /*
     * 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;
    }
  • 相关阅读:
    通过asp.net 生成xml文件
    listbox 多选处理
    girdview 找到其焦点的笨办法
    关于.net 中调用script的alert后 css失效的办法
    从数据库中读数据中寻找若隐若现的OOP
    Gitlab的安装部署和介绍
    守住你的网站:防御DDoS攻击指南
    分析SQL语句使用资源情况
    Linux下Sniffer程序的实现
    NDIS resources
  • 原文地址:https://www.cnblogs.com/gaojian/p/3143632.html
Copyright © 2020-2023  润新知