【大数据 】SparkSQL连接查询中的谓词下推处理(二)
本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/II48YxGfoursKVvdAXYbVg
作者:李勇
目录:
1.左表 join 后条件下推
2.左表join中条件不下推
3.右表join中条件下推
4.右表join中条件不下推
5.总结
在《SparkSql连接查询中的谓词下推处理(一)》中,我们介绍了一些基本的概念,并对内连接查询时的一些基本下推规则进行了分析。
本篇文章要介绍的是--外连接查询中的谓词下推规则,这相比内连接中的规则要复杂一些,不过使用简单的表格来进行分析也是可以分析清楚的。先上表:
我们以左外连接查询为例,先总结规矩如下:
接下来对这个表格中的规则进行详细的分析。
1.左表join后条件下推
查询语句如下:
前文有提到,对于join后条件,如果放在join操作后执行,是可以作为正确结果进行比对的。那么先对两表进行左连接,结果如下:
然后使用LT.id>1这个join后条件进行过滤,结果如下:
来分析一下LT.id>1下推到左表进行数据过滤的结果,经过LT.id>1过滤后,左表变为:
此时再和右表进行左连接,左表id为2的行,在右表中能找到id为2的行,则连接结果如下:
可见,两种处理方法结果一致。条件下推过滤了左表整整50%的数据(相当牛,虽然只过滤了一条)。究其原因,是因为在SparkSQL中,把以上的查询解析成了如下的子查询:
这是一个非相关子查询,即完全可以先完成子查询,再完成父查询,子查询在查询过程中和外部查询没有关联关系。
2.左表join中条件不下推
查询语句如下:
来看看不下推的情况下计算出的正确结果,join过程如下:
第一步:左表id为1的行在右表中能找到相等的id,但是左表的id为1,是不满足第二个join条件(LT.id>1)的,所以左表这一条相当于没有和右表join上,所以左表的值value保留,而右表的value为null(你没满足join中条件没join上还把你的值保留,给我搞个空值?没办法,就是这么任性)。
第二步:左表id为2的行在右表中能找到,而且左表id为2的行的id大于1,两个join条件都满足,所以算是和右表join上了,所以左表和右表的value都保留。最终的查询结果如下:
那么如果把"LT.id>1"这个条件下推到做表,会得到什么结果呢?
首先左表经过"LT.id>1"过滤后,如下:
此时再和右表连接,左表id为2的行在右表中能找到,且满足"LT.id = RT.id AND LT.id > 1"这个join中条件,所以两表的value都被保留。左表中已经没有数据了,查询结束,查询结果如下:
这个查询结果和不下推的正确结果不一致,是个错误的结果,所以左表join中条件是不能下推进行数据过滤的。分析原因:主要是因为join中条件和join后条件对结果的处理方式不同,前者在不满足join条件时会保留一部分结果,而后者在不满足条件时任何东西都不保留。
3.右表join中条件下推
查询语句如下:
现在把RT.id>1这个右表join后条件下推,来过滤右表,过滤后如下:
然后左表再和右表进行左连接,流程如下:
第一步:左表id为1的行在右表中没有,此时左表值保留,右表为null;
第二步:左表id位2的行在右表中有,并且RT.id大于1,两个join条件都满足,则左表和右表的值都保留。查询结果如下:
那么如果不下推(为了得到正确结果),来看看结果,流程如下:
第一步:左表id为1的行在右表中有,但是不满足第二个join条件,所以这行算是没join上,所以左表数据保留,右表为null;
第二步:左表id为2的行在右表中有,也满足第二个join条件,所以左右表的数据都保留。
可见,右表join中条件下推不下推,结果一样,所以,干吗不下推?可以过滤掉一半的数据呢。SparkSQL中的等价处理语句是:
可以看出,也是解析成了一个非相关子查询来处理的。
4.右表join中条件不下推
这个应该是最违反常规理解的查询了,查询语句如下:
首先来看,join后条件不下推的情况,流程如下:
第一步:左表id为1的行在右表中可以找到,但是此时仅仅满足join条件,在使用where条件判断这条连接后数据时,发现右表的id不满足RT.id>1的条件,所以这条join结果不保留(注意:这里是不保留,全都不保留,左表右表都不保留,要跟上边的没join上而右表的值保留为null的情况区别开,这也是关键所在);
第二步:左表id为2的行和右表id为2的行join上了,同时也满足RT.id>1的where条件。
这是一条符合语义的正确的查询结果。
好了,接下来看看右表join后条件下推的情况:
第一步:使用RT.id>1过滤右表,过滤后右表只剩一行id为2的行;
第二步:左表id为1的行在过滤后的右表中没有,此时左表值保留,右表值为null;
第三步:左表id为2的行在右表中有,此时左表值保留,右表值也保留。
结果如下:
很明显这其实是一个错误的结果。
总结
至此,左连接查询的四条规则分析完了。可以看出,在SparkSQL中对于外连接查询时的过滤条件,并不能在所有情况下都用来进行数据源的过滤,如果使用得当会极大的提升查询性能,如果使用不当,则会产生错误的查询结果,而这种错误结果又不易发觉,所以使用时要格外小心。
更多内容敬请关注 vivo 互联网技术 微信公众号
注:转载文章请先与微信号:labs2020 联系。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
持续集成与持续交付之间的联系和区别
作者 | Rebecca Pruess 编译 | 毛智伟 随着DevOps理念的普及与扩散,大家经常会看到持续集成(Continuous Integration)与持续交付(Continuous Delivery)这样的字眼,而怎样使用与选择这些方法成了大多数IT团队必须面对的问题。在讨论更加深入地讨论问题之前,首先需要清楚这两者之间的主要区别是什么,以及用什么方法可以更好改善工作流程,从而在更短的时间内为目标用户提供更高质量的软件。 持续集成(CI)和持续交付(CD)都体现了如今快节奏市场中的文化和发展原则,旨在缩短开发周期、提高软件交付效率以及实现全流程的自动化。同时,两者都有着共同的目标:让软件开发更少地依赖于手动执行的任务,在此基础上使得软件的发布更加频繁、更加安全可靠。由于有着相同的目标,因此持续集成和持续交付并非相互排斥的。只是它们的应用范围有所不同。 那下面就来看下CI与CD之间的联系与区别。 什么是持续集成 如上所述,CI和CD是相互关联的。持续集成是指软件个人研发的部分向软件整体部分交付,频繁进行集成以便更快地发现其中的错误。由此可见,CI专注于定期地让开发人员构建小...
- 下一篇
Docker和Kubernetes中使用Ceph RBD卷的原理分析
在Docker或者Kubernetes中使用Ceph RBD块设备,相比于在宿主机中,是否会对性能造成额外损失?带着这些疑问对相关技术进行原理分析。 Linux中的Mount绑定传播 参考文档: Shared Subtrees; Mount namespaces and shared subtrees; Mount namespaces, mount propagation, and unbindable mounts。 Linux的Mount绑定关系 Linux Mount命名空间通过隔离文件系统挂载点对隔离文件系统提供支持,它是历史上第一个 Linux Namespace,所以它的标识位比较特殊,就是 CLONE_NEWNS。隔离后,不同 Mount Namespace 中的文件结构发生变化也互不影响。你可以通过 /proc/[pid]/mounts 查看到所有挂载在当前 Namespace 中的文件系统,还可以通过 /proc/[pid]/mountstats 看到 Mount Namespace 中文件设备的统计信息,包括挂载文件的名字、文件系统类型、挂载位置等等。 进程在创建...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)