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

基于Oracle的SQL优化--学习(十四)

子查询展开

    子查询展开(SubqueryUnnesting)是优化器处理带子査询的目标SQL的一种优化手段,它是指优化器不再将目标SQL中的子查询当作一个独立的处理单元来单独执行,而是将该子査询转换为它自身和外部查询之间等价的表连接。这种等价表连接转换要么是将子查询拆开(即将该子查询中的表、视图从子查询中拿出来,然后和外部査询中的表、视图做表连接),要么是不拆开但是会把该子査询转换为一个内嵌视图(InlineView),然后再和外部查询中的表、视图做表连接。
    Oracle会确保子查询展开所对应的等价表连接转换的正确性,即转换后的SQL和原SQL在语义上一定是等价的。当然,不是所有的子查询都能做子查询展开,有些子查询是不能做这种等价表连接转换的,这种情况下Oracle就不会对其做子查询展开,也就是说此时Oracle还是会将该子查询当作一个独立的处理单元来单独执行。另外,在Oracle10g及其以后的版本中,对于那种不拆开子查询但是会把该子查询转换成一个内嵌视图的子查询展开(即子查询展开的第二种情形),只有当经过子查询展开后的等价改写SQL的成本值小于原SQL的成本值时,Oracle才会对原SQL执行子查询展开。

    子査询展开通常都会提高原SQL的执行效率,因为如果原SQL不做子查询展开,那么通常情况下该子查询就会在其执行计划的最后一步才被执行,并且会走FILTER类型的执行计划,这也就意味着对于外部查询所在结果集中的每一条记录,该子查询都会被当作一个独立的执行单元来执行一次,外部查询所在的结果集有多少条记录,该子查询就会被执行多少次(可以近似这么理解,实际上并不完全是这样)。这种执行方式的执行效率通常情况下都不会太高,尤其是在子查询中包含两个或者两个以上表连接时,此时做子查询展开后的执行效率往往会比走FILTER类型的执行计划高很多,因为此时优化器就会有其他更多、更高效的执行路径(比如哈希连接)可以选择。
    Oracle数据库里子查询前的where条件如果是如下这些条件之一,那么这种类型的目标SQL在满足了一定的条件后就可以做子查询展开:
    (1)SINGLE-ROW(即=、<、>、<=、>=和?)
    (2)EXISTS
    (3)NOTEXISTS
    (4)IN
    (5)NOTIN
    (6)ANY
    (7)ALL
     如果一个子查询前的where条件是SINGLE-ROW条件,则意味着该子查询的返回结果至多只会返回一条记录;如果该子査询前的where条件是除SINGLE-ROW条件之外的上述其他类型的条件,则该子查询的返回结果就可以包含多条记录。ANY和ALL通常和SINGLE-ROW条件联用,虽然这两个条件我们不常用,但它们的应用范围其实比EXISTS、NOTEXISTS、IN和NOTIN要广很多,比如IN实际上就相当于=ANY,NOT IN实际上就相当于<> ALL。
    子査询是否能做子杳询展开取决于如下两个条件:
    (1)了査询展开所对应的等价改写SQL和原SQL在语义上一定要是完全等价的。如果改写后的SQL和原SQL并不一定能保持语义上的完全等价,这种类型的子查询就不能做子查询展开
    (2)对于不拆开子杳询但是会把它转换为一个内嵌视图的子査询展开,只有当经过子查询展开后的等价改写SQL的成本值小于原SQL的成本值时,Oracle才会对0标SQL执行子查询展开。
    需要注意的是,对于子査询展开的第一种情形(即将子査询拆开,把该子査询中的表、视图从子査询中拿出来,然后和外部査询中的表、视图做表连接),即使是在Oracle10g及其以后的版本中,Oracle也不会考虑子査询展开的成本,即Oracle此时会认为这种情形下子査询展开的效率始终比不展开的效率要离,这也就意味着如果目标SQL满足子査询展开的第一种情形,则Oracle始终会对其做子査询展开,而不管经过子查询展开后的等价改写SQL的成本值是否小于原SQL的成本值。

视图合并

    视图合并(ViewMerging)是优化器处理带视图的目标SQL的一种优化手段,它是指优化器不再将目标SQL中视图的定义SQL语句当作一个独立的处理单元来单独执行,而是会将其拆开,把其定义SQL语句中的基表拿出来与外部査询中的表合并,这样合并后的SQL将只剩下外部查询中的表和原视图中的基表,不再会有视图出现。

    Oracle会确保视图合并的正确性,即合并后的SQL和原SQL在语义上一定是完全等价的。当然,不是所有的视图都能做视图合并,有些视图是不能做视图合并的,这种情况下Oracle就会将该视图的定义SQL语句当作一个独立的处理单元来单独执行。视图合并的好处和子查询展开一样,都是让优化器有更多的执行路径可以选择,而不再拘泥于原视图定义QL语句中的谓词条件、表连接方法、表连接顺序等。    

    Oracle数据库里的视图合并分为简单视图合并、外连接视图合并和复杂视图合并这三种类型。对于符合简单视图合并条件的目标SQL,Oracle始终会对其做视图合并,而不管经过视图合并后的等价改写SQL的成本值是否小于原SQL的成本值。但在Oracle10g及其以后的版本中,对于复杂视图合并,只有等价改写SQL的成本值小于原SQL的成本值时,Oracle才会对目标SQL做复杂视图合并。
简单视图合并

    简单视图合并(SimpleViewMerging)是指针对那些不含外连接,以及所带视图的视图定义SQL语句中不含distinct、groupby等聚合函数的目标SQL的视图合并。

外连接视图合并

    外连接视图合并(OuterJoinViewMerging)是指针对那些使用了外连接,以及所带视图的视图定义SQL语句中不含distinct、groupby等聚合函数的目标SQL的视图合并。这里“使用外连接”的含义是指外部查询的表和视图之间使用了外连接,或者该视图的视图定义SQL语句中使用了外连接。

    外连接会给视图合并带来很多限制,很多在内连接情形下可以做的视图合并一旦换成了外连接就不能做了,因为Oracle能做视图合并的前提条件就是视图合并后的等价改写SQL—定要和原SQL在语义上是完全等价,但对于使用了外连接的目标SQL而言,在很多情况下这种语义上的完全等价性并不能得到保证。
    关于外连接视图合并有一个很常用的限制,即当目标视图在和外部查询的表做外连接时,该目标视图可以做外连接视图合并的前提条件是,要么该视图被作为外连接的驱动表,要么该视图虽然被作为外连接的被驱动表但它的视图定义SQL语句中只包含一个表。



相关文章:

  • 基于Oracle的SQL优化--学习(十五)
  • 基于Oracle的SQL优化--学习(十六)
  • Python获取amap高德地图
  • 基于Oracle的SQL优化--学习(十七)
  • JDK、Spring、Quartz等几种不同定时器的用法,以及cronExpression表达式定义
  • hibernate,将原生SQL执行的结果转换为Map
  • Stimulsoft Reports.Net基础教程(四):创建主从报表②
  • IntelliJ IDEA解决创建maven web项目慢的问题
  • 一些使用IDEA的诀窍
  • Tomcat启动时,webapps目录下的项目没有加载
  • 马哥预习视频
  • Document base xxx does not exist or is not a readable directory
  • 一位资深程序员大牛给予Java初学者的学习路线建议
  • WITH AS的用法
  • pivot的用法
  • Laravel核心解读--Facades
  • Leetcode 27 Remove Element
  • PermissionScope Swift4 兼容问题
  • Spring-boot 启动时碰到的错误
  • VuePress 静态网站生成
  • vue数据传递--我有特殊的实现技巧
  • 番外篇1:在Windows环境下安装JDK
  • 官方解决所有 npm 全局安装权限问题
  • 解决iview多表头动态更改列元素发生的错误
  • 深度学习中的信息论知识详解
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 微信小程序填坑清单
  • 我从编程教室毕业
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • puppet连载22:define用法
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (C语言)fgets与fputs函数详解
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (理论篇)httpmoudle和httphandler一览
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (转)程序员技术练级攻略
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .NET Core Web APi类库如何内嵌运行?
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .net6+aspose.words导出word并转pdf
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • [ 数据结构 - C++] AVL树原理及实现
  • [BZOJ1040][P2607][ZJOI2008]骑士[树形DP+基环树]
  • [codevs 1296] 营业额统计
  • [datastore@cyberfear.com].Elbie、[thekeyishere@cock.li].Elbie勒索病毒数据怎么处理|数据解密恢复
  • [docker] Docker的私有仓库部署——Harbor
  • [ERROR] 不再支持目标选项 5。请使用 7 或更高版本
  • [fsevents@^2.1.2] optional install error: Package require os(darwin) not compatible with your platfo