zoukankan      html  css  js  c++  java
  • 对PostgreSQL源代码中的is_pushed_down的理解

    在PostgreSQL的源代码中,有如下调用关系:

    query_planner
      -->generate_base_implied_equalities
            -->generate_base_implied_qualities_const
                 -->process_implied_equality
                       -->distribute_qual_to_rels

    distribute_qual_to_rels的函数定义如下:

    static void
    distribute_qual_to_rels(PlannerInfo *root, Node *clause,
                            bool is_deduced,
                            bool below_outer_join,
                            JoinType jointype,
                            Relids qualscope,
                            Relids ojscope,
                            Relids outerjoin_nonnullable)
    {
        ...
        /*----------
         * Check to see if clause application must be delayed by outer-join
         * considerations.
         *
         * A word about is_pushed_down: we mark the qual as "pushed down" if
         * it is (potentially) applicable at a level different from its original
         * syntactic level.  This flag is used to distinguish OUTER JOIN ON quals
         * from other quals pushed down to the same joinrel.  The rules are:
         *        WHERE quals and INNER JOIN quals: is_pushed_down = true.
         *        Non-degenerate OUTER JOIN quals: is_pushed_down = false.
         *        Degenerate OUTER JOIN quals: is_pushed_down = true.
         * A "degenerate" OUTER JOIN qual is one that doesn't mention the
         * non-nullable side, and hence can be pushed down into the nullable side
         * without changing the join result.  It is correct to treat it as a
         * regular filter condition at the level where it is evaluated.
         *
         * Note: it is not immediately obvious that a simple boolean is enough
         * for this: if for some reason we were to attach a degenerate qual to
         * its original join level, it would need to be treated as an outer join
         * qual there.    However, this cannot happen, because all the rels the
         * clause mentions must be in the outer join's min_righthand, therefore
         * the join it needs must be formed before the outer join; and we always
         * attach quals to the lowest level where they can be evaluated.  But
         * if we were ever to re-introduce a mechanism for delaying evaluation
         * of "expensive" quals, this area would need work.
         *----------
         */
        if (is_deduced)
        {
            /*
             * If the qual came from implied-equality deduction, it should not be
             * outerjoin-delayed, else deducer blew it.  But we can't check this
             * because the join_info_list may now contain OJs above where the qual
             * belongs.
             */
            Assert(!ojscope);
            is_pushed_down = true;
            ...
        }
        else if (bms_overlap(relids, outerjoin_nonnullable))
        {
            /*
             * The qual is attached to an outer join and mentions (some of the)
             * rels on the nonnullable side, so it's not degenerate.
             *
             * We can't use such a clause to deduce equivalence (the left and
             * right sides might be unequal above the join because one of them has
             * gone to NULL) ... but we might be able to use it for more limited
             * deductions, if it is mergejoinable.    So consider adding it to the
             * lists of set-aside outer-join clauses.
             */
            is_pushed_down = false;
            ...
        }
        else
        {
            /*
             * Normal qual clause or degenerate outer-join clause.    Either way, we
             * can mark it as pushed-down.
             */
            is_pushed_down = true;
    
            ...
        }
        ...
    }

    此时,通过上述调用关系来调用 distribute_qual_to_rels的时候:是这样的:is_deduced参数为真

    void
    process_implied_equality(PlannerInfo *root,
                             Oid opno,
                             Oid collation,
                             Expr *item1,
                             Expr *item2,
                             Relids qualscope,
                             bool below_outer_join,
                             bool both_const)
    {
    ...

         /*
          * Push the new clause into all the appropriate restrictinfo lists.
          */
         distribute_qual_to_rels(root, (Node *) clause,
           true, below_outer_join, JOIN_INNER,
           qualscope, NULL, NULL);
        ...
    }

    此时,is_pushed_down会被设置为true。

    那么,何时会触发此种调用关系呢(由于下面的 and c.cust_id=2 部分的存在而导致):

    postgres=# select * from sales s ,customers c where s.cust_id = c.cust_id and c.cust_id=2;
     cust_id |  item  | cust_id | cust_name 
    ---------+--------+---------+-----------
           2 | camera |       2 | John Doe
    (1 row)
    
    postgres=# 

     继续追击,看看什么条件会触发 distribute_qual_to_rels 函数的 

    else if (bms_overlap(relids, outerjoin_nonnullable)) 分支 和  else 分支:

    调查结果:

    else if (bms_overlap(relids, outerjoin_nonnullable)) 分支

    postgres=# select * from sales s left outer join customers c on s.cust_id = c.cust_id;
     cust_id |   item   | cust_id | cust_name 
    ---------+----------+---------+-----------
           2 | camera   |       2 | John Doe
           3 | computer |       3 | Jane Doe
           3 | monitor  |       3 | Jane Doe
           4 | printer  |         | 
    (4 rows)
    
    postgres=# 

    或者

    postgres=# select * from sales s full outer join customers c on s.cust_id = c.cust_id;
     cust_id |   item   | cust_id | cust_name 
    ---------+----------+---------+-----------
             |          |       1 | craig
           2 | camera   |       2 | John Doe
           3 | computer |       3 | Jane Doe
           3 | monitor  |       3 | Jane Doe
           4 | printer  |         | 
    (5 rows)
    
    postgres=# 

    else分支:

    postgres=# select * from sales s inner join customers c on s.cust_id = c.cust_id;
     cust_id |   item   | cust_id | cust_name 
    ---------+----------+---------+-----------
           2 | camera   |       2 | John Doe
           3 | computer |       3 | Jane Doe
           3 | monitor  |       3 | Jane Doe
    (3 rows)
    
    postgres=# 
  • 相关阅读:
    leetcode教程系列——Binary Tree
    《Ranked List Loss for Deep Metric Learning》CVPR 2019
    《Domain Agnostic Learning with Disentangled Representations》ICML 2019
    Pytorch从0开始实现YOLO V3指南 part5——设计输入和输出的流程
    Pytorch从0开始实现YOLO V3指南 part4——置信度阈值和非极大值抑制
    Pytorch从0开始实现YOLO V3指南 part3——实现网络前向传播
    Pytorch从0开始实现YOLO V3指南 part2——搭建网络结构层
    Pytorch从0开始实现YOLO V3指南 part1——理解YOLO的工作
    让我佩服的人生 文章
    win8.1配置cordova+ionic等一系列东西
  • 原文地址:https://www.cnblogs.com/gaojian/p/3133843.html
Copyright © 2011-2022 走看看