PostgreSQL在何处处理 sql查询之五十七

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介:

接着追踪 ->pathlist:

初始化可能是在这里完成的?

复制代码
/*
 * add_path
 *      Consider a potential implementation path for the specified parent rel,
 *      and add it to the rel's pathlist if it is worthy of consideration.
 *      A path is worthy if it has a better sort order (better pathkeys) or
 *      cheaper cost (on either dimension), or generates fewer rows, than any
 *      existing path that has the same or superset parameterization rels.
 *
 *      We also remove from the rel's pathlist any old paths that are dominated
 *      by new_path --- that is, new_path is cheaper, at least as well ordered,
 *      generates no more rows, and requires no outer rels not required by the
 *      old path.
 *
 *      In most cases, a path with a superset parameterization will generate
 *      fewer rows (since it has more join clauses to apply), so that those two
 *      figures of merit move in opposite directions; this means that a path of
 *      one parameterization can seldom dominate a path of another.  But such
 *      cases do arise, so we make the full set of checks anyway.
 *
 *      There is one policy decision embedded in this function, along with its
 *      sibling add_path_precheck: we treat all parameterized paths as having
 *      NIL pathkeys, so that they compete only on cost.    This is to reduce
 *      the number of parameterized paths that are kept.    See discussion in
 *      src/backend/optimizer/README.
 *
 *      The pathlist is kept sorted by total_cost, with cheaper paths
 *      at the front.  Within this routine, that's simply a speed hack:
 *      doing it that way makes it more likely that we will reject an inferior
 *      path after a few comparisons, rather than many comparisons.
 *      However, add_path_precheck relies on this ordering to exit early
 *      when possible.
 *
 *      NOTE: discarded Path objects are immediately pfree'd to reduce planner
 *      memory consumption.  We dare not try to free the substructure of a Path,
 *      since much of it may be shared with other Paths or the query tree itself;
 *      but just recycling discarded Path nodes is a very useful savings in
 *      a large join tree.  We can recycle the List nodes of pathlist, too.
 *
 *      BUT: we do not pfree IndexPath objects, since they may be referenced as
 *      children of BitmapHeapPaths as well as being paths in their own right.
 *
 * 'parent_rel' is the relation entry to which the path corresponds.
 * 'new_path' is a potential path for parent_rel.
 *
 * Returns nothing, but modifies parent_rel->pathlist.
 */
void
add_path(RelOptInfo *parent_rel, Path *new_path)
{
    bool        accept_new = true;        /* unless we find a superior old path */
    ListCell   *insert_after = NULL;    /* where to insert new item */
    List       *new_path_pathkeys;
    ListCell   *p1;
    ListCell   *p1_prev;
    ListCell   *p1_next;

    /*
     * This is a convenient place to check for query cancel --- no part of the
     * planner goes very long without calling add_path().
     */
    CHECK_FOR_INTERRUPTS();

    /* Pretend parameterized paths have no pathkeys, per comment above */
    new_path_pathkeys = new_path->param_info ? NIL : new_path->pathkeys;

    /*
     * Loop to check proposed new path against old paths.  Note it is possible
     * for more than one old path to be tossed out because new_path dominates
     * it.
     *
     * We can't use foreach here because the loop body may delete the current
     * list cell.
     */
    p1_prev = NULL;
    for (p1 = list_head(parent_rel->pathlist); p1 != NULL; p1 = p1_next)
    {
        Path       *old_path = (Path *) lfirst(p1);
        bool        remove_old = false; /* unless new proves superior */
        PathCostComparison costcmp;
        PathKeysComparison keyscmp;
        BMS_Comparison outercmp;

        p1_next = lnext(p1);

        /*
         * Do a fuzzy cost comparison with 1% fuzziness limit.    (XXX does this
         * percentage need to be user-configurable?)
         */
        costcmp = compare_path_costs_fuzzily(new_path, old_path, 1.01);

        /*
         * If the two paths compare differently for startup and total cost,
         * then we want to keep both, and we can skip comparing pathkeys and
         * required_outer rels.  If they compare the same, proceed with the
         * other comparisons.  Row count is checked last.  (We make the tests
         * in this order because the cost comparison is most likely to turn
         * out "different", and the pathkeys comparison next most likely.  As
         * explained above, row count very seldom makes a difference, so even
         * though it's cheap to compare there's not much point in checking it
         * earlier.)
         */
        if (costcmp != COSTS_DIFFERENT)
        {
            /* Similarly check to see if either dominates on pathkeys */
            List       *old_path_pathkeys;

            old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys;
            keyscmp = compare_pathkeys(new_path_pathkeys,
                                       old_path_pathkeys);
            if (keyscmp != PATHKEYS_DIFFERENT)
            {
                switch (costcmp)
                {
                    case COSTS_EQUAL:
                        outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
                                                   PATH_REQ_OUTER(old_path));
                        if (keyscmp == PATHKEYS_BETTER1)
                        {
                            if ((outercmp == BMS_EQUAL ||
                                 outercmp == BMS_SUBSET1) &&
                                new_path->rows <= old_path->rows)
                                remove_old = true;        /* new dominates old */
                        }
                        else if (keyscmp == PATHKEYS_BETTER2)
                        {
                            if ((outercmp == BMS_EQUAL ||
                                 outercmp == BMS_SUBSET2) &&
                                new_path->rows >= old_path->rows)
                                accept_new = false;        /* old dominates new */
                        }
                        else    /* keyscmp == PATHKEYS_EQUAL */
                        {
                            if (outercmp == BMS_EQUAL)
                            {
                                /*
                                 * Same pathkeys and outer rels, and fuzzily
                                 * the same cost, so keep just one; to decide
                                 * which, first check rows and then do a fuzzy
                                 * cost comparison with very small fuzz limit.
                                 * (We used to do an exact cost comparison,
                                 * but that results in annoying
                                 * platform-specific plan variations due to
                                 * roundoff in the cost estimates.)  If things
                                 * are still tied, arbitrarily keep only the
                                 * old path.  Notice that we will keep only
                                 * the old path even if the less-fuzzy
                                 * comparison decides the startup and total
                                 * costs compare differently.
                                 */
                                if (new_path->rows < old_path->rows)
                                    remove_old = true;    /* new dominates old */
                                else if (new_path->rows > old_path->rows)
                                    accept_new = false; /* old dominates new */
                                else if (compare_path_costs_fuzzily(new_path, old_path,
                                              1.0000000001) == COSTS_BETTER1)
                                    remove_old = true;    /* new dominates old */
                                else
                                    accept_new = false; /* old equals or
                                                         * dominates new */
                            }
                            else if (outercmp == BMS_SUBSET1 &&
                                     new_path->rows <= old_path->rows)
                                remove_old = true;        /* new dominates old */
                            else if (outercmp == BMS_SUBSET2 &&
                                     new_path->rows >= old_path->rows)
                                accept_new = false;        /* old dominates new */
                            /* else different parameterizations, keep both */
                        }
                        break;
                    case COSTS_BETTER1:
                        if (keyscmp != PATHKEYS_BETTER2)
                        {
                            outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
                                                   PATH_REQ_OUTER(old_path));
                            if ((outercmp == BMS_EQUAL ||
                                 outercmp == BMS_SUBSET1) &&
                                new_path->rows <= old_path->rows)
                                remove_old = true;        /* new dominates old */
                        }
                        break;
                    case COSTS_BETTER2:
                        if (keyscmp != PATHKEYS_BETTER1)
                        {
                            outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
                                                   PATH_REQ_OUTER(old_path));
                            if ((outercmp == BMS_EQUAL ||
                                 outercmp == BMS_SUBSET2) &&
                                new_path->rows >= old_path->rows)
                                accept_new = false;        /* old dominates new */
                        }
                        break;
                    case COSTS_DIFFERENT:

                        /*
                         * can't get here, but keep this case to keep compiler
                         * quiet
                         */
                        break;
                }
            }
        }

        /*
         * Remove current element from pathlist if dominated by new.
         */
        if (remove_old)
        {
            parent_rel->pathlist = list_delete_cell(parent_rel->pathlist,
                                                    p1, p1_prev);

            /*
             * Delete the data pointed-to by the deleted cell, if possible
             */
            if (!IsA(old_path, IndexPath))
                pfree(old_path);
            /* p1_prev does not advance */
        }
        else
        {
            /* new belongs after this old path if it has cost >= old's */
            if (new_path->total_cost >= old_path->total_cost)
                insert_after = p1;
            /* p1_prev advances */
            p1_prev = p1;
        }

        /*
         * If we found an old path that dominates new_path, we can quit
         * scanning the pathlist; we will not add new_path, and we assume
         * new_path cannot dominate any other elements of the pathlist.
         */
        if (!accept_new)
            break;
    }

    if (accept_new)
    {
        /* Accept the new path: insert it at proper place in pathlist */
        if (insert_after)
            lappend_cell(parent_rel->pathlist, insert_after, new_path);
        else
            parent_rel->pathlist = lcons(new_path, parent_rel->pathlist);
    }
    else
    {
        /* Reject and recycle the new path */
        if (!IsA(new_path, IndexPath))
            pfree(new_path);
    }
}
复制代码

目前为止,追踪遇到可困难,此路暂时不通。

考虑其他方向。

这个还是很重要的:

复制代码
/*
 * 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)
{
    ///fprintf(stderr,"In set_plain_rel_pathlist \n");

    /* 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);
}
复制代码
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
1天前
|
SQL NoSQL Java
Java使用sql查询mongodb
通过使用 MongoDB Connector for BI 和 JDBC,开发者可以在 Java 中使用 SQL 语法查询 MongoDB 数据库。这种方法对于熟悉 SQL 的团队非常有帮助,能够快速实现对 MongoDB 数据的操作。同时,也需要注意到这种方法的性能和功能限制,根据具体应用场景进行选择和优化。
23 9
|
22天前
|
SQL 存储 人工智能
Vanna:开源 AI 检索生成框架,自动生成精确的 SQL 查询
Vanna 是一个开源的 Python RAG(Retrieval-Augmented Generation)框架,能够基于大型语言模型(LLMs)为数据库生成精确的 SQL 查询。Vanna 支持多种 LLMs、向量数据库和 SQL 数据库,提供高准确性查询,同时确保数据库内容安全私密,不外泄。
92 7
Vanna:开源 AI 检索生成框架,自动生成精确的 SQL 查询
|
29天前
|
SQL Java
使用java在未知表字段情况下通过sql查询信息
使用java在未知表字段情况下通过sql查询信息
36 8
|
1月前
|
SQL 安全 PHP
PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全
本文深入探讨了PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全。
59 4
|
1月前
|
SQL 监控 关系型数据库
SQL语句当前及历史信息查询-performance schema的使用
本文介绍了如何使用MySQL的Performance Schema来获取SQL语句的当前和历史执行信息。Performance Schema默认在MySQL 8.0中启用,可以通过查询相关表来获取详细的SQL执行信息,包括当前执行的SQL、历史执行记录和统计汇总信息,从而快速定位和解决性能瓶颈。
|
1月前
|
SQL 存储 缓存
如何优化SQL查询性能?
【10月更文挑战第28天】如何优化SQL查询性能?
151 10
|
1月前
|
SQL 关系型数据库 MySQL
|
1月前
|
SQL 关系型数据库 数据库
PostgreSQL性能飙升的秘密:这几个调优技巧让你的数据库查询速度翻倍!
【10月更文挑战第25天】本文介绍了几种有效提升 PostgreSQL 数据库查询效率的方法,包括索引优化、查询优化、配置优化和硬件优化。通过合理设计索引、编写高效 SQL 查询、调整配置参数和选择合适硬件,可以显著提高数据库性能。
366 1
|
2月前
|
SQL 数据库 开发者
功能发布-自定义SQL查询
本期主要为大家介绍ClkLog九月上线的新功能-自定义SQL查询。
|
1月前
|
SQL 关系型数据库 MySQL
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
35 0