博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PostgreSQL在何处处理 sql查询之五十二
阅读量:6812 次
发布时间:2019-06-26

本文共 7832 字,大约阅读时间需要 26 分钟。

开始

/*     * 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 voidset_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 voidset_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);                else                    set_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 voidset_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. */voidset_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。

得仔细研究。

本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2013/06/06/3119002.html,如需转载请自行联系原作者

你可能感兴趣的文章
CCNA第3次课程
查看>>
Gson详解:Java对象与JSON相互转换的利器
查看>>
U-mail邮件系统又一getshell
查看>>
另辟蹊径,挑战网络战争
查看>>
Spring Boot 入门
查看>>
路由交换调试(CCNA)零基础到专家 二
查看>>
我的友情链接
查看>>
.Net组件程序设计之序列化
查看>>
读书笔记-SQL Server 数据页缓冲区的内存瓶颈分析
查看>>
Rollup Cube Grouping Set使用总结
查看>>
python中字符串类型与字典类型相互转换
查看>>
python3第一天(基础语法)
查看>>
【MySQL】《高性能MySQL》学习笔记,第四章,Schema与数据类型优化
查看>>
曲线插值-N阶Bezier贝塞尔曲线生成
查看>>
DM网页设计
查看>>
LAMP Stack
查看>>
我的友情链接
查看>>
七大法宝让手机App摆脱“火一把就死”魔咒
查看>>
高手整理入门笔记(启动篇)
查看>>
Performance Counter Registry Hive Consistency
查看>>