• 对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=# 
  • 相关阅读:
    PAT:1075. PAT Judge (25) AC
    PAT:1010. 一元多项式求导 (25) AC
    PAT:1076. Forwards on Weibo (30) AC
    PAT:1086. Tree Traversals Again (25) AC
    PAT:1020. Tree Traversals (25) AC
    PAT:1051. Pop Sequence (25) AC
    PAT:1063. Set Similarity (25) AC
    PAT:1017. A除以B (20) AC
    C语言指针
    iOS block
  • 原文地址:https://www.cnblogs.com/gaojian/p/3133843.html
Copyright © 2020-2023  润新知