Oracle数据库12c release 2优化器详解

序言:优化器是Oracle数据库最引人入胜的部件之一,因为它对每一个SQL语句的处理都必不可少。优化器为每个SQL语句确定最有效的执行计划,这是基于给定的查询的结构,可用的关于底层对象的统计信息,以及所有与优化器和执行相关的特性。

本文来自Oracle 白皮书翻译(译者:苏旭辉 newkid),介绍了在Oracle数据库12c第二版中与优化器和统计信息相关的所有新特性并且提供了简单的,可再现的例子,使得你能够更容易地熟悉它们,尤其是当你从早先的版本进行迁移的时候。它还概括了已有的功能是如何被增强以改善性能和易管理性。 有些Oracle优化器特性已经被从本文移除,并在它们自己的文章中被讨论。具体来说,它们是:

  • 优化统计信息和优化统计信息顾问
  • SQL计划管理
  • 近似查询处理

为了得知Oracle优化器的全貌,我们建议你结合参考文献部分列出的相关文件来阅读本文。

一、自适应查询优化 到目前为止,Oracle 12c数据库中最大的变化是自适应查询优化。自适应查询优化是这样的一组功能,它们使得优化器能够对执行计划进行实时调整,并且发现能够导致更佳的统计信息的额外信息。当现有的统计信息不足以产生一个最佳的计划,这种新方法是极其有用的。自适应查询优化包括两个方面:

自适应计划,它着重于改善一个查询的执行;

自适应统计信息,它利用额外的信息来改善查询执行计划。

(图1:新的自适应查询优化功能的构成组件)

Oracle数据库12c第二版默认启用的自适应功能与Oracle数据库12c第一版不同。详细信息请参见下面的“初始化参数”部分。

二、自适应计划 优化器在某些条件下会选择自适应计划; 例如,当查询包括连接和复杂谓词,使得准确地估计基数变得很困难。自适应计划使得优化器能够把一个语句的计划推迟到执行的时候才确定。优化器在它所选择的计划(缺省计划)中植入统计收集器,从而在运行的时候,它能够判断基数估算与计划的操作所实际看到的行数是否有很大的偏差。如果有显著的区别,那么这个计划或者计划的一部分就会被自动调整,以避免不理想的性能。 三、自适应的连接方式 通过为计划中的某些分支预先确定多个子计划,优化器能够实时调整连接方式。例如,在图2中优化器的缺省计划为orders(订单)和 products(产品)表之间的连接选定的是嵌套循环连接,通过对products表的索引读取。另一个可选的子计划也同时被确定,它允许优化器将连接方式切换到哈希连接。在候选计划中products是通过全表扫描来读取的。

在初次执行的时候,统计收集器收集了关于这次执行的信息,并且将一部分进入到子计划的数据行缓存起来。 优化器会确定要收集哪些统计信息,以及如何根据统计的不同值来确定计划。它会算出一个“拐点”,两个计划选项在这个值是一样好的。

例如,如果当orders表的扫描产生的行数少于10行,则嵌套循环连接是最佳,当 orders 表的扫描产生的行数多于10行,则哈希连接是最佳,那么这两个计划的拐点就是10。优化器会算出这个值,并且配置一个缓存统计收集器,使得它缓存并且计数至10行为止。如果扫描产生了至少10行,那么连接方式就被确定为哈希连接;否则,它就被确定为嵌套循环连接。在图2中,统计信息收集器正在监控和缓存来自orders表全扫描的数据行。基于从统计信息收集器中看到的信息,优化器会决定使用哪个子计划。

在这个例子中,哈希连接被选中,因为来自orders表的行数大于优化器最初的估计。

(图2:orders 和 products 表之间的连接的自适应执行计划。左边是缺省计划,右边是选中的计划) 优化器能够从嵌套连接切换到哈希连接,反之亦然。可是,如果初始选中的连接方法是排序合并连接,则自适应不会发生。 在缺省情况下,explain plan命令只会显示优化器选定的初始(缺省)计划。而DBMS_XPLAN.DISPLAY_CURSOR函数显示的是查询实际使用的计划。

(图3: Explain plan 和 DBMS_XPLAN.DISPLAY_CURSOR 为图2所示的情形所输出的计划) 为了看到自适应计划中所有的操作,包括统计收集器的位置,你必须在DBMS_XPLAN函数中指定额外的格式参数'adaptive'。在这个模式下,计划的id栏会出现一个额外的“-”记号,指明在计划中未被采用(非激活)的操作。

(图4: 在DBMS_XPLAN.DISPLAY_CURSOR中使用'ADAPTIVE'格式参数得到的完整自适应计划) 如果在“Plan”下拉框中选择“Full”,SQL监控工具(SQL Monitor)将显示所有的操作。计划的非活动部分变灰(参见图5)。如果点击“Plan Note”图标,一个弹出框会被显示,确认该计划是一个自适应计划。

(图5: SQL Monitor显示一个自适应计划) 四、自适应并行分配方法 当一个SQL语句以并行模式执行时,某些操作,例如排序,聚合和连接,它们要求在执行语句的并行服务进程之间重新分配数据。优化器所用的分配方法取决于操作方式,涉及到的并行服务进程数,以及预期的行数。如果优化器对行数估算不准确,那么选中的分配方法就可能不理想,并可能导致某些并行服务进程得不到充分利用。 随着新的自适应分配方法"混合型哈希"(HYBRID HASH)的引入,优化器可以将分配方法延迟到执行的时候才确定,此时它对于涉及到的数据行数就有了更多的信息。一个统计收集器被插入到操作之前,如果缓存的数据的实际行数比阈值小,则分配方法将从哈希(HASH)切换到广播(BROADCAST)。然而,如果缓冲的行数达到了阈值,则分配方法将会是哈希(HASH)。阈值的定义为并行度的两倍。 图6显示了SQL监控工具中的一个执行计划的例子,它是一个以并行模式执行的EMP和DEPT表之间的连接。一组并行服务进程(生产者,即粉红色图标)扫描两个表并且将数据行送给另一组并行服务进程(消费者,即蓝色图标),该组进程是连接的真正执行者。优化器决定采用混合型哈希(HYBRID HASH)的分配方法。在这个连接中访问的第一个表是DEPT表。来自DEPT表的数据行被缓存在统计收集器中,见计划的第六行,直至阈值被超越,或者最后一行被获取。在那时优化器将会决定采用何种分配方法。

(图6: SQL监控工具中的一个EMP和DEPT表之间的连接的执行计划,它使用了自适应分配方法) 要了解在运行时选择哪个分配方法,查找此信息的最简单方法是查看SQL监控工具中的OTHER列。 此列在PX SEND HYBRID HASH的行中显示一个望远镜图标。当你点击这个图标时,你可以看到运行时使用的分配方法。

(图7: 混合型哈希分配法) 这个对话框中显示的自适应分配方法有三种可能的值:6 = BROADCAST(广播), 5 = ROUND-ROBIN(循环制), 16 = HASH(哈希)。 五、自适应位图索引裁剪 当优化器生成了一个星型转换计划,它就必须选择正确的位图索引组合,以尽可能有效地减少相关的ROWID集合。如果有多个索引,其中的一些可能不会显著地减少ROWID集合,但是仍然会在查询执行期间引入可观的处理成本。自适应计划因此被用来裁剪索引,这些索引无法显著地降低过滤匹配的行数。 在带有adaptive关键字的SQL执行计划中,DBMS_XPLAN.DISPLAY_CURSOR 将会显示自适应的位图裁剪,其方式类似于图3所示的示例。

例如,考虑以下SQL执行计划,它显示出位图索引CAR_MODEL_IDX被裁剪掉:

(图8: 自适应位图索引裁剪的例子) 六、自适应统计信息 优化器所确定的执行计划的质量取决于可用的统计信息的质量。然而,有些查询谓词变得过于复杂,以至于无法单独依赖于基表的统计信息,而现在优化器能够用自适应统计信息来进行增补。 七、动态统计信息 在一个SQL语句的编译过程中,优化器会判断已有的统计信息是否足以产生一个好的执行计划,或者它该考虑使用动态取样。动态取样是为了补偿缺失或者不充足的统计信息,如果不这么做,这样的信息可能导致非常糟糕的计划。在查询中的一个或者多个表的统计信息都缺失的情况下,优化器在优化语句之前就会在这些表上使用动态取样来收集基本的统计信息。这种情况下收集的统计信息在质量(因为是取样)和完整性上都不如使用DBMS_STATS包收集到的信息。 从Oracle数据库 12c第一版开始, 动态取样被强化为动态统计信息。动态统计信息允许优化器强化现有的统计信息以获取更加精确的基数估算,不仅仅是为单表的访问,而且也包含连接和分组(GROUP BY)谓词。并且,从Oracle数据库12c第一版开始, 初始化参数OPTIMIZER_DYNAMIC_SAMPLING引入了新的取样级别11。11级使得优化器能够自动为任何SQL语句使用动态统计信息,即使所有基本的表统计信息都已经存在。优化器做出使用动态统计的决定,是基于所用谓词的复杂性,和已经存在的基础统计信息,以及预期的SQL语句总执行时间。例如,之前的优化器在某些情况下会使用猜测的方法,比如带有LIKE谓词和模糊匹配的查询,而现在则会启用动态统计信息。 缺省的动态取样级别是2, 因此,当级别设置为11时,动态取样启用的频率很可能大大超过以往。这会增加语句的解析时间。为了将对性能的影响减到最低,在Oracle数据库12c第一版中,动态取样查询的结果将会被保留在数据库的服务器结果缓存,从Oracle数据库12c第二版开始会保留在SQL计划指令的知识库中。这就允许多个SQL语句来共享一组由动态取样收集的统计信息。下面将要更详细讨论的SQL计划指令也会利用这种级别的动态取样。 八、自动重优化 在一个SQL语句的首次执行期间,一个执行计划如常被生成。在优化的过程中,有些已知的低质量估算种类(例如,对缺少统计信息的表的估算,或者带有复杂谓词的表的估算)会被做记号,对产生的游标的监控会被开启。如果系统开启了对一个游标的反馈监控,计划中的基数估算就被用来与执行过程中看到的实际基数进行比较。如果估算值被发现和实际基数有显著区别,则优化器会在下次执行寻求可替换的计划。优化器会利用前一次执行收集到的信息来帮助确定这个替换计划。优化器可能将一个查询重新优化好几次,每次都学习并且进一步改善计划。Oracle 12c数据库支持多种不同形式的重优化。 九、统计信息反馈 统计信息反馈(以前称为基数反馈,cardinality feedback)是重优化的一种形式,它自动为那些反复执行的具有基数估算误差的查询改善计划。在一个SQL语句的首次执行期间,优化器生成了一个执行计划,并且决定是否应该为游标启动统计信息反馈监控器。统计信息反馈在如下的情形被启用:缺失统计信息的表,表上有多个合取或者析取谓词(指用AND或者OR连接起的谓词), 谓词包含有复杂操作,使得优化器不能准确估算基数。 在查询结束之时,优化器将它原来的基数估算和在执行期间观测到的实际基数进行比较,如果估算值和实际值有显著差异,它会将正确的值存储起来供后续使用。它还会创建一个SQL计划指令,使得其他的SQL语句也能受益于这次初始执行中学到的信息。如果查询再次执行,优化器会使用纠正过的基数估算值,而不是它原先的估算值,来确定执行计划。如果它发现初始的估算值是正确的,则不会采取任何额外的措施。在第一次执行之后,优化器关闭了统计信息反馈的监控。 图9显示了一个SQL语句受益于统计信息反馈的例子。在这个两表连接的初次执行中,由于customers表上有多个相关的单列谓词,优化器将基数低估了8倍。

(图9: 一个受益于自动重优化的统计信息反馈的SQL语句初次执行的情况) 当估计值和实际返回的行数有很大的差别,这个游标被标记为IS_REOPTIMIZIBLE(可重优化)并且不会被再次使用。IS_REOPTIMIZIBLE属性指明这个SQL语句应该在下一次执行的时候被硬解析,所以优化器能够使用在初次执行时记录下来的统计信息来确定一个更佳的执行计划。

(图10: 在初次执行的统计信息与原有的基数估算有显著差异之后,游标被标识为可重优化) 一个SQL计划指令同样被创建,这是为了确保下次如果在customers表使用了相似的谓词的SQL语句被执行,优化器会注意到这些列之间的相关性。 在第二次执行,优化器使用了来自初次执行的统计信息来确定一个具有不同连接顺序的新计划。在生成执行计划的过程中对统计信息反馈的使用情况被注明于执行计划下面的备注部分。

(图11: 新生成的计划使用来自初次执行的统计信息) 新计划没有标识为IS_REOPTIMIZIBLE,所以它将被这个SQL语句的所有后续执行所使用。

(图12: 新生成的计划标识为不可重优化) 十、性能反馈 重优化的另一种形式为性能反馈,当自动并行度(AutoDOP)在自适应模式下被启用,这会有助于改善重复执行的SQL语句的并行度的选择(参见第25页上的OPTIMIZER_ADAPTIVE_STATISTICS内容)。

(注:关于自动并行度请参见参考文章5 “Oracle数据库12c并行执行基础知识”)

当自动并行度(AutoDOP)在自适应模式下被启用,在一个SQL语句的首次执行过程中,优化器会决定语句是否应该在并行模式下执行;如果是,应该使用哪种并行度。并行度的选择是基于语句的预计性能表现。对于优化器决定并行执行的任何SQL语句,额外的性能监视器同样在初次执行的时候被打开, 在初次执行结束时,优化器选择的并行度,和根据语句初次执行期间的实际性能统计信息(例如CPU时间)计算出来的并行度,被加以比较。如果两个值有显著差别,那么语句被标识为可重优化,初次执行的性能统计信息被作为反馈存储起来,以帮助为后续的执行计算出一个更加合适的并行度。 如果性能反馈被用于一个SQL语句,它会在计划下方的备注部分被注明,如图13所示。

(图13: 一个SQL语句的执行计划,性能反馈发现它串行执行会更好)

建议阅读原文了解更多的内容。

原文下载地址:http://www.oracle.com/technetwor ... edb-12c-1963236.pdf

原文发布于微信公众号 - 数据和云(OraNews)

原文发表时间:2017-03-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏皮振伟的专栏

[linux][memory]ksm/uksm的调优和优化尝试

前言: 在前文《[linux][memory]KSM技术分析》中,分析了KSM技术的基本实现原理。这里再总结一下使用ksm/uksm遇到的几个问题,并附加上作者...

42412
来自专栏linux驱动个人学习

CPUFreq驱动

CPUFreq子系统位于 drivers/cpufreq目录下,负责进行运行过程中CPU频率和电压的动态调整,即DvFS( Dynamic Voltage Fr...

743
来自专栏Aloys的开发之路

编程获得CPU的主频

CPU的主频,即CPU内核工作的时钟频率(CPU Clock Speed)。CPU的主频表示在CPU内数字脉冲信号震荡的速度。主频和实际的运算速度存在一定的关系...

2018
来自专栏take time, save time

三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,后面会在gitbook上...

2596
来自专栏腾讯大数据的专栏

Storm上的实时统计利器-easycount

背景 Storm是TRC(腾讯实时计算)平台的核心组件。与Hadoop不同,storm之上没有像hive,pig之类的解放应用开发人员效率的工具。开发原生的st...

2619
来自专栏芋道源码1024

从一次 Snowflake 异常说起

1. 异常概述 2018年1月26日下午,业务方信贷小组的同学反馈服务执行数据库插入操作出现异常,异常信息显示数据库主键出现重复: ? 在仔细分析了用户的重复主...

1.2K5
来自专栏杨建荣的学习笔记

增量数据丢失的原因分析(r8笔记第26天)

今天开发的同事找到我,让我帮他们补一部分数据,因为有一个表的数据已经快一个月没有增量数据了,这个需求听起来有些奇怪是不? 问题的背景是在统计库中存在一个表,供部...

2988
来自专栏Java技术栈

百度三轮面试回来,想和Java程序员分享一下。

如果要去百度面试的,提前做好充足的准备吧,不然你会败的很惨。下面整理下我从百度三轮面试回来的题目,供你参考! 一,百度一面 1、给一个函数,返回 0 和 1...

4249
来自专栏数据和云

insert into太慢?Roger 带你找真凶

李真旭(Roger) ACOUG 核心专家,Oracle ACE,云和恩墨技术专家 编辑手记:昨天谈到索引并不是万能的,事实上很多无用的索引给数据库带来很大的维...

2974
来自专栏杨建荣的学习笔记

使用在线重定义重构亿级分区表(r10笔记第34天)

在我的印象中,一直以来都会收到一封报警邮件,之前分析过,排查过,最后发现是一个遗留问题,协调开发同学,停业务维护还是有一些难度,最后不了了之了,在今天又突然想起...

3708

扫描关注云+社区