当前位置: 首页 > news >正文

对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=# 
复制代码





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

相关文章:

  • Readings in Databases
  • 使用python处理selenium中的鼠标悬停问题
  • nginx 防火墙、权限问题
  • Swift 2 0 所有新特性
  • Xcode真机调试出现The account '***' has no team with ID '***'的解决方案
  • 关于Autolayout制作动画的坑
  • iOS解析HTMl标签以及开发中的一些坑
  • iOS10判断摄像机是否可用
  • Android类似微信图片选择器
  • 使用MaxCompute搭建社交好友推荐系统
  • C 标准库 - stdio.h
  • [LeetCode] Verify Preorder Sequence in Binary Search Tree 验证二叉搜索树的先序序列
  • linux学习笔记四
  • 如何优雅地为Struts2的action加监控日志
  • Oracle12C_____处理数据库01033连接错误问题.sql
  • 网络传输文件的问题
  • 自己简单写的 事件订阅机制
  • [iOS]Core Data浅析一 -- 启用Core Data
  • 77. Combinations
  • css的样式优先级
  • C语言笔记(第一章:C语言编程)
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • Java|序列化异常StreamCorruptedException的解决方法
  • JWT究竟是什么呢?
  • React as a UI Runtime(五、列表)
  • Shadow DOM 内部构造及如何构建独立组件
  • vuex 笔记整理
  • Yii源码解读-服务定位器(Service Locator)
  • 高度不固定时垂直居中
  • 给第三方使用接口的 URL 签名实现
  • 和 || 运算
  • 算法之不定期更新(一)(2018-04-12)
  • 通过npm或yarn自动生成vue组件
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转)ORM
  • (轉)JSON.stringify 语法实例讲解
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • @JoinTable会自动删除关联表的数据
  • [ C++ ] STL_list 使用及其模拟实现
  • [.NET]桃源网络硬盘 v7.4
  • [17]JAVAEE-HTTP协议
  • [AX]AX2012 AIF(四):文档服务应用实例
  • [C]整形提升(转载)
  • [daily][archlinux][game] 几个linux下还不错的游戏
  • [FC][常见Mapper IRQ研究]
  • [hdu 1711] Number Sequence [kmp]
  • [HTML]Web前端开发技术30(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页
  • [I2C]I2C通信协议详解(二) --- I2C时序及规格指引
  • [Java] 图说 注解
  • [LeetCode] 596:超过5名学生的课