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

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

开始

/*     * 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://lkqax.baihongyu.com/

你可能感兴趣的文章
telnet :No route to host
查看>>
基本安装lnmp环境
查看>>
yum源资料汇总
查看>>
7、MTC与MTV,http请求介绍
查看>>
logstash消费阿里云kafka消息
查看>>
第四节课作业
查看>>
EasyUI Calendar 日历
查看>>
unix 环境高级编程
查看>>
为数据库建立索引
查看>>
第二周作业-软件工作量的估计
查看>>
MAXIMO 快速查找实现
查看>>
Oracle——条件控制语句
查看>>
[Linux][Redis][05]Benchmark
查看>>
第一次作业-准备篇
查看>>
HDU1848 Fibonacci again and again
查看>>
HTML思维导图
查看>>
git改密码出现授权问题
查看>>
ORA-02266: 表中的唯一/主键被启用的外键引用
查看>>
Django的POST请求时因为开启防止csrf,报403错误,及四种解决方法
查看>>
day-6 and day-7:面向对象
查看>>