oracle 12c 11g 区别收集统计信息在11g和12C下的区别

Oracle 10g 11g 12c的区别简单介绍
查看数: 2839|
评论数: 0|
22:12 上传
Oracle 10g 11g 12c 区别
Oracle Database 10g 是第一个为网格计算设计的数据库管理系统。Oracle Database 11g 合并和扩展了 Oracle 特有的功能以实现网格计算的优势,将数据中心从分散的系统资源孤岛转换为包含服务器和存储的共享池。Oracle Database 12c 和 Enterprise Manager Cloud Control 是为云计算设计的。云计算创建了一个完整的、预先集成的现成专用云解决方案,从而可以快速将企业数据中心转换为专用云。主要优势如下所示:o通过合并使用少数几个服务器,降低对大量服务器的需求并提高 CPU 的利用率。o通过自动部署标准数据库配置,缩短 DBA 花在安装和配置数据库上的时间。o通过单一控制台管理整个云生命周期(规划、设置、交付和运行)。o通过为各个用户设置限额,防止资源独占。o通过分析趋势报表,预测未来资源需求。o基于性能和配置度量计算计费。数据库技术 第10页_Linux公社-Linux系统门户网站
你好,游客
数据库技术
今天在Oracle 11g的环境上制造数据碰到ORA-30009: CONNECT BY 操作内存不足,10g开始支持XML后,改为xmltable就可以了。
日期:11/21/:40
作者:stevendbaguo
由于控制文件对于数据库的重要性很高,所以通常在dbca建库以后,都会对控制文件多路复用。如,在oracle10g中,默认控制文件有3份,内容完全一致,通常位于$ORACLE_BASE/oradata/SID/下面,名字为control01.ctl,control02.ctl,control03.ctl,而到了11g,默认只有2个份,一个位于$ORACLE_BASE/oradata/SID/下面,名字为control01.ctl,另一份位于$ORACLE_BASE/fast_recovery_area/SID/下面,名字为control02.ctl。
日期:11/21/:23
作者:aaron8219
上周去给客户培训Oracle,讲到DG部分做实际配置演示的时候,碰到了ORA-28547故障,客户的数据库时11.2.0.1的版本,Window平台。之前已经按照步骤把DG全部配置完成了,当准备在备库启用redo apply的时候,照例先检查一下两边远程归档路径是否有效:
日期:11/21/:25
作者:aaron8219
总所周知,用exp/imp对数据库进行逻辑备份,包括表,用户,整个数据库,我们通常所熟悉的是使用命令行指定参数的方式来做的。下面我来演示一下不太常用的以交互方式的操作,操作很简单,就是只要输入exp/imp的命令,以交互方式提供导入导出所需的参数来完成。虽然这种方式没有实际的应用意义,但作为Oracle提供的一种方法,我们也是有必要熟悉一下的。
日期:11/21/:01
作者:aaron8219
腾讯互娱内部维护了一个MySQL分支,基于官方5.5.24,实现了类似于Oracle 11g的快速加字段功能,这个分支我们内部称为TMySQL。该功能通过扩展存储格式来实现,原理类似于Oracle 11g,以下介绍下其实现原理。
日期:11/21/:26
作者:Linux
MySQL表结构修改详解
日期:11/21/:39
作者:Linux
MySQL 在修改表结构的时候可能会中断产品的正常运行影响用户体验,甚至更坏的结果,丢失数据。不是所有的数据库管理员、程序员、系统管理员都非常了解MySQL能避免这种情况。DBA会经常碰到这种生产中断的情况,当升级脚本修改了应用层和数据库层,或者缺乏经验的管理员、开发在不是很了解Mysql内部工作机制的情况下修改了规范文件。
日期:11/21/:15
作者:whats_java
MongoDB中使用MapReduce进行分组统计
日期:11/20/:00
作者:gzinfo
记录一次ORA-600[13013]处理过程,在一次数据库的异常处理完成后,发现alert日志中出现ORA-600[13013]错误
日期:11/20/:01
作者:Linux
ORA-08102这种错误说明索引或表出现了数据不一致的,索引上记录的键值和表里的数据不一致,引起访问失败,一般重建下索引就可以解决
日期:11/20/:12
作者:kingdba
Oracle用户与权限管理
日期:11/20/:34
作者:dushuai
Oracle增强型日期函数
日期:11/20/:39
作者:dushuai
ROLLUP()函数是对于GROUP BY 分组统计的功能扩展,可以实现分组统计求和的效果。
日期:11/20/:00
作者:dushuai
Oracle的Job 运行久了会产生大量运行日志,job日志级别由两个因素决定,一个是job自己日志级别,别一个是使用的job cloass的日志级别,取两者中的最高值。
日期:11/19/:29
作者:qytag
Oracle数据库复制或克隆后,经常需要修改用户名和密码,下面总结下修改的方法和步骤:
日期:11/19/:43
作者:qytag
Oracle Instanc Client安装命令工具
日期:11/19/:54
作者:fan_hai_ping
MariaDB是一个开源数据库且100%与MySQL兼容,目标是替代MySQL数据库。本篇我们会讨论如何在Ubuntu上安装MariaDB。默认上MariaDB的包并没有在Ubuntu仓库中。要安装MariaDB,我们首先要设置MariaDB仓库。
日期:11/19/:26
作者:Linux
Oracle Database 12C发布好长时间了,这几天尝试了下单机、RESTART和RAC的安装,其中发生了不少趣事。比如安装Oracle 12c Restart花费了4小时多最终笔记本死机、RAC安装过程中采用HAIP特性却失败等等。
日期:11/18/:49
作者:Linux
Oracle 12C引入了CDB与PDB的新特性,在ORACLE 12C数据库引入的多租用户环境(Multitenant Environment)中,允许一个数据库容器(CDB)承载多个可插拔数据库(PDB)。CDB全称为Container Database,中文翻译为数据库容器,PDB全称为Pluggable Database,即可插拔数据库。在ORACLE 12C之前,实例与数据库是一对一或多对一关系(RAC):即一个实例只能与一个数据库相关联,数据库可以被多个实例所加载。而实例与数据库不可能是一对多的关系。当进入ORACLE 12C后,实例与数据库可以是一对多的关系。下面是官方文档关于CDB与PDB的关系图。
日期:11/18/:40
作者:静以致远√团团
RAC 开启关闭(Oracle 12C 小记)
日期:11/18/:33
作者:静以致远√团团
RedHat6.5 安装Oracle 12C RAC
日期:11/18/:53
作者:静以致远√团团
Oracle 12C引入了CDB与PDB的新特性,在ORACLE 12C数据库引入的多租用户环境(Multitenant Environment)中,允许一个数据库容器(CDB)承载多个可插拔数据库(PDB)。CDB全称为Container Database,中文翻译为数据库容器,PDB全称为Pluggable Database,即可插拔数据库。在ORACLE 12C之前,实例与数据库是一对一或多对一关系(RAC):即一个实例只能与一个数据库相关联,数据库可以被多个实例所加载。而实例与数据库不可能是一对多的关系。当进入ORACLE 12C后,实例与数据库可以是一对多的关系。下面是官方文档关于CDB与PDB的关系图。
日期:11/18/:22
作者:静以致远√团团
在Oracle 12c R1之前,一个字段是无法以任何形式拥有多个索引的。或许有人会想知道为什么通常一个字段需要有多重索引,事实上需要多重索引的字段或字段集合是很多的。在12c R1中,只要索引类型的形式不同,一个字段就可以包含在一个B-tree索引中,同样也可以包含在Bitmap索引中。注意,只有一种类型的索引是在给定时间可用的。
日期:11/18/:01
作者:静以致远√团团
Oracle版本:Oracle Rac 11.2.0.3之前打了11.2.0.3.9的补丁集,Rac装上还没正式用,所以就干脆再打到最新的11.2.0.3.11补丁集。
日期:11/17/:32
作者:sunjiapeng
AIX7.1 + 双节点Oracle Rac 11.2.0.3,由于此套Rac并非自己部门安装,是开发部安装,现交由运维部分来管理,客户需要要将asm& diskgroup name 安装部门规范来命令。遂需要将oasmdgdata1更改为datadg。幸好Oracle的版本是11gR2,在11gR2中,Oracle有一项新特性,可以直接使用renamedg命令更改diskgroup的名称。
日期:11/17/:58
作者:sunjiapeng
SunOS 5.10Oracle 10.2.0.2.0开发环境某一数据库出现ORA-600报错。
日期:11/17/:43
作者:sunjiapeng
这篇文章是我们自己亲手实验过的,系统为 Ubuntu 14.04 server,Mysql 数据库为 Mysql 5.5,准备迁移到 Maria DB 10.1 版本,关于其他版本的迁移方法详细的说明你可以去官方查看,这里我只说说我所实验过的。
日期:11/17/:28
作者:Linux
MySQL中的事件调度器可以定时对数据库增加,删除和执行操作,相当于数据库中的临时触发器,与Linux系统中的执行计划任务一样,这样就可以大大降低工作量。&
日期:11/17/:50
作者:tongcheng
Oracle数据库中rman备份脚本非常实用
日期:11/17/:59
作者:jxzhfei
修改Oracle重做日志文件大小
日期:11/17/:00
作者:jxzhfei
MySQL优化之BTree索引使用规则
日期:11/16/:33
作者:buyingfei8888
什么是延迟索引?使用索引查询出来数据,之后把查询结果和同一张表中数据进行连接查询,进而提高查询速度!
日期:11/16/:12
作者:buyingfei8888
如果你的MySQL数据库文件较大,可能备份的时候需要占用很多服务器资源,所以站长要尽量选择访客最少的时间段执行自动备份命令,比如凌晨4-5点左右。而且要注意给备份留下足够的时间然后执行存储命令。
日期:11/14/:09
作者:phpfenghuo
最近学习Oracle数据库,在虚拟机中的Windows XP SP3系统中安装了Oracle 10g(版本:Oracle_10g_10.2.0.1_win32)。
日期:11/14/:10
作者:zht666
今天突然发现连接数据库时报错,用pl/sql dev连接数据时,有时能连接上,有时连接时报:ORA-12520: TNS: 监听程序无法找到需要的服务器类型的可用句柄通过服务器登录数据库,报下面的报连接数错误:[oracle@dbserver22 ~]$ sqlplus"/as sysdba"
日期:11/14/:29
作者:lichangzai
今天我遇到一个问题,MySQL企业版备份引起I/O子系统负载过大,应用响应缓慢,导致系统不可用。所以我想限制mysqlbackup的进程,使它不会引起更多的问题。
日期:11/14/:46
作者:ifeixiang
10/347...10...查看: 129|回复: 0
本帖最后由 考拉大兵 于
13:05 编辑
作者: Maria Colgan
发表于 2013年6月
优化器是数据库最吸引人的部件之一,因为它对每一个SQL语句的处理都必不可少。优化器为每个SQL语句确定最有效的执行计划,这是基于给定的查询的结构,可用的关于底层对象的统计信息,以及所有与优化器和执行相关的特性。
随着每个新版本的发布,优化器都会进化,利用新功能以及新的统计信息来生成更好的执行计划。随着对查询优化的新的自适应方法的引入,Oracle 12c数据库把这种进化更推上了一个台阶。
这份白皮书介绍了在Oracle 12c数据库中与优化器和统计相关的所有新特性并且提供了简单的,可再现的例子,使得你能够更容易地熟悉它们。它还概括了已有的功能是如何被增强以改善性能和易管理性。
优化器和统计信息新特性
自适应查询优化
到目前为止,Oracle 12c数据库中最大的变化是自适应查询优化。自适应查询优化是这样的一组功能,它使得优化器能够对执行计划进行实时调整,并且发现能够导致更佳的统计信息的额外信息。当现有的统计信息不足以产生一个优化的计划,这种新方法是极其有用的。自适应查询优化包括两个方面:自适应计划,它着重于改善一个查询的初次执行;自适应统计信息,它为后续的执行提供了额外的信息。
(图1,自适应查询优化功能的组件)
自适应计划
自适应计划使得优化器能够延迟产生一个语句的最终计划,直到执行的时候才决定。优化器在它所选择的计划(缺省计划)中植入统计收集器,从而在运行的时候,它能够判断自己的基数估算与计划的操作所实际看到的行数是否有很大的偏差。如果有显著的区别,那么这个计划或者计划的一部分在SQL语句的首次执行就能够被自动调整来避免不理想的性能。
自适应的连接方式
通过为计划中的某些分支预先确定多个子计划,优化器能够实时调整连接方式。例如,在图2中优化器的初始计划(缺省计划)为order_items 和 product_info 之间的连接选定的是嵌套循环连接,通过对product_info表的索引读取。另一个可选的子计划也同时被确定,它允许优化器将连接方式切换到哈希连接。在候选计划中product_info是通过全表扫描来读取的。
在执行的时候,统计收集器收集了关于这次执行的信息,并且将一部分进入到子计划的数据行缓存起来。在这个例子中,统计收集器监控并缓存了对order_items的全表扫描。基于它在统计收集器中看到的信息,优化器会最终确定采用哪个子计划。在这个例子中,哈希连接被选为最终计划,因为来自order_items表的行数大于优化器最初的估计。在优化器选择了最终计划之后,统计收集器停止收集统计信息以及对数据行的缓存,而仅仅是传递数据。在子游标随后的执行中,优化器禁止了数据缓存,并且选择了同一个最终计划。目前的优化器能够从嵌套连接切换到哈希连接,反之亦然。可是,如果初始选中的连接方法是排序合并连接,则自适应不会发生。
(图2,自适应执行计划确定Order_items 和 Prod_info 表之间的连接)
在缺省情况下,explain plan命令只会显示优化器选定的初始(缺省)计划。而DBMS_XPLAN.DISPLAY_CURSOR只显示查询所用的最终计划。
(图3. Explain plan 和 DBMS_XPLAN.DISPLAY_CURSOR 为图2的查询例子所输出的计划)
为了看到自适应计划中所有的操作,包括统计收集器的位置,你必须在DBMS_XPLAN函数中指定额外的格式参数'+adaptive'。在这个模式下,id栏会出现一个额外的(-)记号,指明在计划中未被采用(非激活)的操作。在企业管理器(OEM)中的SQL监控工具总是显示完整的自适应计划,但是并没有指明在计划中的哪些操作是非激活的。
(图4. 在DBMS_XPLAN.DISPLAY_CURSOR中使用'+adaptive'格式参数得到的完整自适应计划)
V$SQL中增加了一不新的列(IS_RESOLVED_ADAPTIVE_PLAN)来指明一个SQL语句是否有自适应计划,以及该计划是否已经完全被确定。如果IS_RESOLVED_ADAPTIVE_PLAN被设置为'Y', 这意味着计划不仅是自适应的,而且最终计划已被选定。可是,如果IS_RESOLVED_ADAPTIVE_PLAN被设置为'N', 这指明了选定的计划是自适应的,但是最终计划仍未被确认。'N'值仅仅在一个查询的初始执行阶段中可见,在此之后,自适应计划的这个值总是为'Y'。对于非自适应计划这个列被设置为NULL。
你也可以通过将初始化参数OPTIMIZER_ADAPTIVE_REPORTING_ONLY设置为TRUE(缺省值是FALSE),从而把自适应连接方式置于报告模式。在这个模式下,开启自适应连接方式所需的信息会被收集,但是改变计划的任何动作都不会发生。这意味着缺省计划总是会被采用,但是关于计划在“非报告”模式下会如何调整的信息将被收集。这个信息可以在自适应计划的报告中被查看,当你用额外的格式参数'+report'显示计划的时候就可以看到。
(图5. 在DBMS_XPLAN.DISPLAY_CURSOR中使用'+report'格式参数所显示的完整自适应报告)
自适应并行分配方法
当一个SQL语句以并行模式运行时,某些操作,例如排序,聚合和连接,它们要求在执行语句的并行服务进程之间重新分配数据。优化器所用的分配方法取决于哪种操作,涉及到的并行服务进程数,以及预期的行数。如果优化器对行数估算不准确,那么选中的分配方法就可能不理想,结果某些并行服务进程就可能得不到充分利用。
随着新的自适应分配方法&混合型哈希&(HYBRID HASH)的引入,优化器可以将分配方法的确定延迟到执行的时候才确定,此时它对于涉及到的数据行数就有了更多的信息。一个统计收集器被插入到操作之前,如果缓存的数据的实际行数比阈值小,则分配方法将从哈希(HASH)切换到广播(BROADCAST)。然而,如果缓冲的行数达到了阈值,则分配方法将会是哈希(HASH)。阈值的定义为并行度的两倍。
图6显示了SQL监控工具中的一个执行计划的例子,它是一个以并行模式执行的EMP和DEPT表之间的连接。一组并行服务进程(生产者,即粉红色图标)扫描两个表并且将行送给另一组并行服务进程(消费者,即蓝色图标),该组进程是连接的真正执行者。优化器决定采用混合型哈希(HYBRID HASH)的分配方法。在这个连接中访问的第一个表是DEPT表。来自DEPT表的数据行被缓存在统计收集器中,见计划的第六行,直至阈值被超越,或者最后一行被获取。在那时优化器将会决定采用何种分配方法。
(图6. SQL监控工具中的一个EMP和DEPT表之间的连接的执行计划,它使用了自适应分配方法。
我们假定这个例子中的并行度被设置为6, 从DEPT表扫描返回的行数是4, 阈值则是12行(2X6)。既然还未达到阈值,从DEPT表返回的4行将会被广播到负责完成连接的6个并行服务进程,结果计划中的分配步骤所处理的行数是是24行(4X6),见图7。既然对于来自DEPT表的数据行采用了广播(BROADCAST)的分配方法,来自EMP表的数据行将会通过循环制(ROUND-ROBIN)的方法进行分配。这意味着来自EMP表的一行数据将会轮流发送给6个并行服务进程中的一个,知道所有的数据行都分配完毕。
(图7, 混合型哈希分配法使用广播的分配方式,因为未达到阈值)
可是,如果这个例子的并行度被设置为2, 而扫描DEPT表返回的行数为4, 则阈值为4行(2X2)。既然已经达到了阈值,从DEPT表返回的4行数据将会以哈希(HASH)的方式分配到负责完成连接的2个并行服务进程, 结果计划中的分配步骤所处理的行数是是4行(见图8)。既然来自DEPT表的数据行采用了哈希(HASH)分配发,来自EMP表的数据也会以哈希(HASH)方法进行分配。
(图8, 混合型哈希分配法使用哈希的分配方式,因为已达到阈值)
自适应统计信息
优化器所确定的执行计划的质量取决于可用的统计信息的质量。然而,有些查询谓词变得过于复杂,以至于无法单独依赖于基表的统计信息,而现在优化器能够用自适应统计信息来进行增补。
动态统计信息
在一个SQL语句的编译过程中,优化器会判断已有的统计信息是否足以产生一个好的执行计划,或者它该考虑使用动态取样。动态取样是为了补偿缺失或者不充足的统计信息,如果不这么做,这样的信息可能导致非常糟糕的计划。在查询中的一个或者多个表的统计信息都缺失的情况下,优化器在优化语句之前就会在这些表上使用动态取样来收集基本的统计信息。这种情况下收集的统计信息在质量(因为是取样)和完整性上都不如使用DBMS_STATS包收集到的信息。
在Oracle 12c数据库中, 动态取样被增强为动态统计信息。动态统计信息允许优化器增强现有的统计信息以获取更加精确的基数估算,不仅仅是为单表的访问,而且也包含连接和分组(GROUP BY)谓词。初始化参数OPTIMIZER_DYNAMIC_SAMPLING引入了新的取样级别11。11级使得优化器能够自动为任何SQL语句使用动态统计信息,即使所有基本的表统计信息都已经存在。优化器做出使用动态统计的决定,是基于所用谓词的复杂性,和已经存在的基础统计信息,以及预期的SQL语句总执行时间。例如,之前的优化器在某些情况下会使用猜测的方法,比如带有LIKE谓词和模糊匹配的查询,而现在则会弃用动态统计信息。
(图9. 当 OPTIMIZER_DYNAMIC_SAMPLING 被设为级别 11,动态取样会被使用,而不是猜测)
在这些新的条件下,当级别设置为11时,动态取样启用的频率很可能超过以往。这会增加语句的解析时间。为了将对性能的影响减到最低,动态取样查询的结果将会作为动态统计信息保留在缓存中,允许其他SQL语句来共享这些统计信息。SQL计划指令(下面将会更详细地讨论)也会利用这种级别的动态取样。
自动重优化
和自适应计划不同的是,在初次执行之后,自动重优化在随后的执行中修改计划。在一个SQL语句的初次执行结束之时,优化器利用初次执行期间收集到的信息来决定自动重优化是否值得。如果执行的信息和优化器原有的估计值有显著区别,则优化器会在下次执行寻求替换的计划。优化器会利用前一次执行收集到的信息来帮助确定这个替换计划。优化器可能将一个查询重新优化好几次,每次都学习并且进一步改善计划。Oracle 12c数据库支持多种不同形式的重优化。
统计信息反馈
统计信息反馈(以前称为基数反馈,cardinality feedback)是重优化的一种形式,它自动为那些反复执行的具有基数估算误差的查询改善计划。在一个SQL语句的首次执行期间,优化器生成了一个执行计划,并且决定是否应该为游标启动统计信息反馈监视器。统计信息反馈在如下的情形被启用:缺失统计信息的表,表上有多个合取或者析取谓词(指AND或者OR连接的谓词), 谓词包含有复杂操作,使得优化器不能准确估算基数。
在查询结束之时,优化器将它原来的基数估算和在执行期间观测到的实际基数进行比较,如果估算值和实际值有显著差异,它会将正确的值存储起来供后续使用。它还会创建一个SQL计划指令,使得其他的SQL语句也能受益于这次初始执行中学到的信息。如果查询再次执行,优化器会使用纠正过的基数估算值,而不是它原先的估算值,来确定执行计划。如果它发现初始的估算值是正确的,则不会采取任何额外的措施。在第一次执行之后,优化器关闭了统计信息反馈的监视。
图10显示了一个SQL语句受益于统计信息反馈的例子。在这个两表连接的初次执行中,由于customers表上有多个相关的单列谓词,优化器将基数低估了8倍。
(图10, 一个受益于自动重优化的统计信息反馈的SQL语句初次执行的情况)
在初次执行之后,优化器将它原来的基数估算和计划中的操作实际返回的行数进行比较。估计值和实际返回的行数有很大的差别,所以这个游标被标记为IS_REOPTIMIZIBLE(可重优化)并且不会被再次使用。IS_REOPTIMIZIBLE属性指明这个SQL语句应该在下一次执行的时候被硬解析,所以优化器能够使用在初次执行时记录下来的统计信息来确定一个更佳的执行计划。
(图11. 在初次执行的统计信息与原有的基数估算有显著差异之后,游标被标识为可重优化)
一个SQL计划指令同样被创建,这是为了确保下次如果在customers表使用了相似的谓词的SQL语句被执行,优化器会注意到这些列之间的相关性。
在第二次执行,优化器使用了来自初次执行的统计信息来确定一个具有不同连接顺序的新计划。统计信息反馈在执行计划的生成中的使用情况被注明于执行计划下面的备注部分。
(图12. 新生成的计划使用来自初次执行的统计信息)
新计划没有标识为IS_REOPTIMIZIBLE,所以它将被这个SQL语句的所有后续执行所使用。
(图13. 新生成的计划标识为不可重优化)
重优化的另一种形式为性能反馈,当自动并行度(AutoDOP)在自适应模式下被启用,这会有助于改善重复执行的SQL语句的并行度的选择。(注:关于AutoDOP的更多信息请参照Oracle并行执行基础白皮书)
当自动并行度(AutoDOP)在自适应模式下被启用,在一个SQL语句的首次执行过程中,优化器会决定语句是否应该在并行模式下执行;如果是,应该使用哪种并行度。并行度的选择是基于语句的预计性能表现。对于优化器决定并行执行的任何SQL语句,额外的性能监视器同样在初次执行的时候被打开,
在初次执行结束时,优化器选择的并行度,和根据语句初次执行期间的实际性能统计信息(例如CPU时间)计算出来的并行度,被加以比较。如果两个值有显著差别,那么语句被标识为可重优化,初次执行的性能统计信息被作为反馈存储起来,以帮助为后续的执行计算出一个更加合适的并行度。
如果性能反馈被用于一个SQL语句,它会在计划下方的备注部分被注明,如图14所示。
注意:哪怕AutoDOP不在自适应模式下被启用,性能反馈也可能影响一个语句的并行度选择。
(图14. 一个SQL语句的执行计划,性能反馈发现它串行执行会更好)
SQL计划指令
SQL计划指令是根据通过自动重优化学习到的信息所创建出来的。一个SQL计划指令是一些额外的信息, 优化器可用来生成一个更优的执行计划。例如,当发生连接的两个表在连接列有倾斜数据,SQL计划指令可以指引优化器使用动态统计信息来获得更加精确的连接基数估算。
SQL计划指令是在查询表达式之上创建的,而非语句级或者对象级,这样就可确保它们可被应用于多个SQL语句。在一个SQL语句上有多个SQL计划指令也是可能发生的。一个SQL语句所使用的SQL计划指令数目被显示于执行计划下方的备注部分(图15)。
(图15. 一个语句所使用的SQL计划指令数目被显示于执行计划下方的备注部分)
数据库自动维护SQL计划指令,并把它们存储在SYSAUX表空间。任何未被使用的SQL计划指令在53周之后会被自动清除。SQL计划指令也可以通过DBMS_SPD包手动管理。然而,你不可能手动创建一个SQL计划指令。SQL计划指令可以通过视图DBA_SQL_PLAN_DIRECTIVES和DBA_SQL_PLAN_DIR_OBJECTS进行监控(见图16)。
如前所述,当图10所示的SQL语句被发现优化器的基数估算和计划中的操作所返回的实际行数有显著差异时,一个SQL计划指令就被创建。实际上,有两个SQL计划指令被自动创建。一个是为了纠正在customers表上由于多个单列谓词之间的相关性所导致的基数估算偏差,一个是为了纠正sales表上的基数估算偏差。
(图16. 查看根据通过自动重优化学习到的信息所创建出来的SQL计划指令)
在目前仅有一种类型的SQL计划指令,即&动态取样(DYNAMIC_SAMPLING)&。这会告诉优化器,如果看到了这个特定的查询表达式(例如,在country_id, cust_city, 和 cust_state_province上一起使用的过滤谓词),它就应该使用动态取样来纠正基数估算的偏差。
SQL计划指令同样被ORACLE用来确定扩展统计信息(特别是列群组)是否缺失,是否基数估算偏差能被列群组所纠正。如果是这样的话,它会在下一次收集统计信息的时候自动在相应的表上创建那个列群组。于是如果可能的话,扩展信息就会取代SQL计划指令被使用在SQL计划中(等值谓词,group by分组等等)。如果SQL计划指令已经没必要存在,它会在53周后被自动清除。
(注:关于扩展统计信息的更多信息可见文章“理解优化器统计信息”)
举个例子,在前面的例子中,SQL计划指令被创建于customers表。这个SQL计划指令被创建的原因是多个单列谓词之间的相关性。 一个CUST_CITY, CUST_STATE_PROVINCE,和 COUNTRY_ID上的列群组就可以解决基数估算偏差。下一次收集customers表的统计信息的时候,这个列群组就会被自动创建。
(图17. 基于SQL计划指令自动创建的列群组)
下次这个SQL语句被执行的时候,列群组统计信息就会取代SQL计划指令被使用。DBA_SQL_PLAN_DIRECTIVES中的state(状态)列指明了一个SQL计划指令在这个周期中目前处于哪个环节。
一旦单表的基数估算被解决,额外的SQL计划指令可能被创建于同样的语句来解决计划中的其他问题,例如连接和分组的基数估算偏差。
06:40 上传
(图18, 随着时间推移,为图10中所见的SQL语句所创建的多个SQL计划指令)
优化器统计信息
优化器统计信息是描述数据库以及里面的对象的数据的集合。优化器利用这些统计信息来为每个SQL语句选择最佳的执行计划。对于任何一个Oracle系统,为了把性能维持在一个可接受的水平,及时收集适当的统计信息是至关重要的。随着每个新版本的发布,Oracle一直致力于自动提供必要的统计信息。
新型的直方图
直方图告诉优化器,数据在一个列中是如何分布的。在缺省情况下,优化器假定在一个列中,数据行是跨越不同的值均匀分布的, 在带有等值谓词查询中,基数的计算方法是将总行数除以等值谓词所用到的列中的不同值的个数。直方图的存在改变了优化器用来确定基数估算的公式,并且允许它生成更精确的估算值。在Oracle 12c之前,有两种类型的直方图:频度和等高直方图。现在多了两种额外的直方图,即顶级频度直方图和混合直方图。
顶级频度直方图
在过去,如果一个列有超过254个不同值而且指定的桶数为AUTO, 那么一个等高直方图就会被创建。但如果99%或者更多的数据所含有的不同值少于254个,会怎么样?如果等高直方图被创建,那么就存在这种风险,即不能将表中最频繁的值捕获为多个桶的端点值。因此有些频繁值就会被当作非频繁值处理,这会导致不理想的执行计划被选中。
在这种情况下,为了创建一个质量更加的直方图,更好的方法是在构成了表中数据的主体的那些极为频繁的值之上创建一个频度直方图,并且忽略那些非频繁值。一个频度直方图被创建于列中最频繁出现的那些值,当这些值出现在表中99%的数据或者更多。这允许列中所有频繁出现的值被当作频繁值来处理。仅当收集统计指令的ESTIMATE_PERCENT参数被设置为AUTO_SAMPLE_SIZE时,一个顶级频度直方图才会被创建,这是因为列中所有的值都必须被看到,才能确定是否达到必要的标准(99.6%的数据具有254个或者更少的不同的值)。
以PRODUCT_SALES表为例,这个表含有一个圣诞饰物公司的销售数据。表中有 1.78M 行,共有632个不同的TIME_ID。但是PRODUCT_SALES数据的主体含有少于254个不同的值,因为每年的圣诞饰物主要都在12月销售。为了让优化器知道列中的数据发生倾斜,有必要在TIME_ID列上创建一个直方图。在这个情况下,一个含有254个桶的顶级频度直方图被创建。
(图19. PRODUCT_SALES表中TIME_ID列数据的分布情况,以及之上所创建的顶级频度直方图)
混合直方图
在前一个版本,当一个列中不同值的个数大于254, 一个等高直方图就会被创建。在等高直方图中,只有在两个或两个以上的桶中作为端点出现的值才会被认为是频繁值。等高直方图的一个突出问题是,一个频度落在总群体的1/254和2/254之间的值可能会也可能不会作为一个频繁值出现。虽然它可能横跨两个桶,它可能只在一个桶中作为端点值出现。这样的值被认为是近似频繁值。等高直方图无法区分近似频繁值和真正非频繁值。
混合直方图类似于传统的等高直方图,因为它只在列中不同值的个数大于254的时候才会被创建。可是,相似性也仅限于此。在混合直方图中,没有任何一个值会出现在多个桶的端点,这就允许直方图包含更多的端点值,实际上也就是比等高直方图具有更多的桶数。那么,混合直方图是如何标识频繁值的?每个端点的频度被记录下来(在一个新的名为endpoint_repeat_count的列中),这样就为每个端点值提供了更精确的指示。
以CUSTOMERS表的CUST_CITY_ID列为例。CUSTOMERS表中有55,500行数据,CUST_CITY_ID列有620个不同的值。在这种情况下频度直方图和顶级频度直方图都不合适。在Oracle 11g数据库中,一个等高直方图将会被创建在这个列上。这个等高直方图有213个桶但是只代表了42个频繁值(出现在2个或更多的桶的端点的值)。CUST_CITY_ID列中实际的频繁值个数是54(即,出现频度大于总行数/桶数=的那些值有54个)。
在Oracle 12c数据库中,一个混合直方图会被创建。混合直方图有254个桶,并且代表了所有54个频繁值。实际上混合直方图将63个值当作频繁值。这意味着在Oracle 11g数据库中被当作近似频繁值(只在一个桶中作为端点值)现在被处理为频繁值,并且将会有更精确的基数估算。图20显示了一个例子,在Oracle 11g数据库中的一个近似频繁值(52114)如何在Oracle 12c数据库中得到更佳的基数估算。
在 CUST_CITY_ID=52114的数据总共有227行:
(图 20. 混合直方图使得那些Oracle 11g数据库中被当作近似频繁值的值得到更精确的基数估算)
统计信息在线收集
当一个索引被创建,全表扫描是必不可少的,Oracle顺便加上统计信息的收集,将自动收集优化器统计信息作为索引创建任务的一部分。现在,同样的技术也被应用于直接路径操作,例如create table as select (CTAS)和insert as select(IAS)操作。将统计信息收集搭载为数据加载操作的一部分,意味着在数据加载结束之后,不需要额外的全表扫描就可以立即拥有统计信息。
(图21. 统计信息在线收集为新创建的SALES2表同时提供了表统计和列统计信息)
统计信息在线收集并不包括收集直方图或者索引统计,因为这些类型的统计信息需要额外的扫描,这可能会对数据加载的性能造成很大的影响。为了收集必要的直方图和索引统计,而不需重新收集基础列统计信息,请使用DBMS_STATS.GATHER_TABLE_STATS过程并将options参数设置为新的GATHER AUTO选项。
(图22. 将 options 设为 GATHER AUTO 在SALES2表上创建了直方图而无需收集基础统计信息)
备注列中的“HISTOGRAM_ONLY”指明直方图在没有重新收集基础列统计的情况下被收集。GATHER AUTO选项仅在统计信息的在线收集发生之后被推荐使用。
有两种方法可以确定统计信息的在线收集是否发生:检查执行计划,看看新的数据源OPTIMIZER STATISTICS GATHERING是否在计划中出现,或者查看USER_TAB_COL_STATISTICS表的新的NOTES列,看看是否有状态值STATS_ON_LOAD。
(图23. 统计信息在线收集操作的执行计划)
根据设计,统计信息在线收集对直接路径操作的性能影响要最小化,因此它只能发生于空对象的数据加载。在向一张现有的表的新的分区中加载数据的时候,为了确保统计信息在线收集能够发生,请使用扩展的语法来显式指定分区。在这种情况下,分区级别的统计信息会被创建,但是全局(表级别)统计信息不会被修改。如果增量统计信息在分区表上被打开,一份纲要也会作为数据加载的一部分被创建。(译注: 纲要(synopsis)是在表分区级别收集的辅助统计信息,包含这个分区的某个列的不同值(NDV)的清单,根据这个信息可以推算出全表的不同值)
(图24. 在往现有分区表插入操作时发生了统计信息在线收集)
注意,在语句级别指定提示NO_GATHER_OPTIMIZER_STATISTICS可以关闭统计信息在线收集。
全局临时表上的会话级统计信息
全局临时表通常用于存储应用程序上下文中的中间结果。一个全局临时表的定义,是全系统中拥有适当权限的所有用户所共享的,但其数据永远是会话私有的。在全局临时表(必须是会话级临时表,PRESERVE ROWS ON COMMIT,提交时保留数据)上收集统计信息是行得通的;然而,在前一个版本中,收集到的统计信息会被所有访问这张表的会话所使用。如果不同会话之间在临时表中存储的数据量或者数据的性质有巨大差异,这样就不太理想了。
现在,每个使用临时表的会话都可以有一份单独的统计信息。临时表上共享的统计信息可以通过一个新的DBMS_STATS选项GLOBAL_TEMP_TABLE_STATS来进行控制。在缺省情况下,这个选项被设置为SESSION,意思是每个访问临时表的回航都会有自己的一套统计信息。优化器会试图先使用会话的统计信息,但是如果会话统计信息不存在,那么优化器会使用共享统计信息。如果你想回到以前的表现,即仅有一份统计信息被所有会话所使用,可以将GLOBAL_TEMP_TABLE_STATS选项设为SHARED。
(图25. 将全局临时表不共享统计信息的缺省表现修改为强制共享统计信息)
当通过直接路径操作往一张全局临时表中填充数据(提交时保留数据的那种),会话级的统计信息会被自动创建,这是由于统计信息在线收集的作用,它免除了额外运行统计信息收集指令的必要性,并且不会影响其他会话使用的统计信息。
(图26. 使用直接路径加载对全局临时表填充数据会导致会话级别的统计数据被自动收集)
DBMS_STATS包中的新的报告子程序
对于任何一个系统,为了维持一个可接受的性能水平,知道何时收集、如何收集及时的统计信息是至关重要的。想要确定一个环境中正在执行的是什么样的统计信息收集操作,对统计方法的变动将会如何影响系统,这可能是一项困难且耗时的任务。在Oracle 12c数据库中, 新的报告子程序被加入到DBMS_STATS包中,使得我们更易于监控何种统计收集活动正在进行,以及对这些操作的参数进行修改会有什么影响。
REPORT_STATS_OPERATIONS
这个新函数生成一个报表,显示的是关于在特定的时间窗口内发生了何种统计收集活动的详细信息。报表给出的细节包括每种操作何时发生,状态如何,覆盖了多少个对象。报表可以输出为文本或者HTML格式。
(图27. 生成一个新的 DBMS_STATS.REPORT_STATS_OPERATIONS 报表)
REPORT_SINGLE_STATS_OPERATION
这个新函数生成一个关于指定的统计信息收集操作的详细报表。
REPORT_GATHER_*_STATS
这组新的函数实际上并不会收集统计信息,但是会报告一个对象的列表,假如对应的GATHER_*_STATS过程被以相同的参数设定所调用,这些对象将会被处理。REPORT_GATHER_*_STATS接受的输入参数和对应的GATHER_*_STATS过程相同,多了两个额外参数:详细级别以及格式。
(图28. 生成新的DBMS_STATS.REPORT_GATHER_SCHEMA_STATS 报表)
新的优化技术
在查询优化的过程中,Oracle会使用一系列复杂的技术对SQL语句进行变换。查询优化的这个阶段的目标是为了将原来的SQL语句变换为一个语义上等价、但是处理起来更加高效的SQL语句。Oracle 12c数据库引入了几种新的查询优化方法。
部分连接取值
部分连接取值是这样一种优化技术,它是在连接顺序的生成过程中被使用的。这种技术的目标是为了避免产生重复的行,如果不用这种技术,这些重复只能在计划中随后用一个DISTINCT操作符来去除。通过早些用一个内连接(INNER JOIN)或者半连接(SEMI-JOIN)来取代DISTINCT操作符,这一步骤产生的行数将会减少。这应该会使得计划的总体性能得到改善,因为随后的步骤只需在缩小的行的集合上进行操作。这种优化可以应用在如下类型的查询块:MAX(),MIN(), SUM(distinct), AVG (distinct), COUNT (distinct), 以及UNION, MINUS, INTERSECT 操作符的分支, [NOT] EXISTS 子查询等等。
考虑如下的DISTINCT查询:
SELECT DISTINCT order_id
&&FROM orders o, customers c
WHERE o.customer_id = c.customer_id
& && & AND order_id & 2400;
(译者注:这个例子举得不好。order_id在orders中应该是唯一的,customer_id在customers表中也应该是唯一的,所以连接之后order_id在结果中也应该是唯一的,DISTINCT完全多余)
在Oracle 11g数据库中,ORDERSh CUSTOMERS之间的连接是一个哈希连接(HASH JOIN),必须在去除重复行的排序发生前被完全取值。
(图29. Oracle 11g数据库要求在ORDERS 和 CUSTOMERS之间完全的连接,然后用unique sort去除重复)
有了部分连接取值,ORDERS 和 CUSTOMERS之间的连接被转换为一个半连接,这意味着一旦在CUSTOMERS表中找到一个匹配的CUSTOMER_ID,查询就会转移到下一个CUSTOMER_ID。通过将哈希连接转换为半连接,流入SORT UNIQUE 的行数大大减少,因为重复的行已经被去除了。变换过的SQL的计划如图30所示。(译者注:变换之后是HASH UNIQUE不是SORT UNIQUE)
(图 30. Oracle 12c数据库的计划显示了ORDERS 和 CUSTOMERS之间完全的半连接,没有产生重复的行)
接受空值的半连接
应用开发者在包含EXISTS子查询的SQL语句中加入IS NULL谓词是不罕见的。加入额外的IS NULL谓词是因为 EXISTS子查询产生的半连接结果会去除具有空值的行,正如内连接(INNER JOIN)所做的一样。
考虑如下的查询:
SELECT p.prod_id,s.quantity_sold,s.cust_id
&&FROM products p, sales s
WHERE p.prod_list_price & 11
& && &&&AND p.prod_id = s.prod_id
& && &&&AND (s.cust_id IS NULL
& && && && & OR EXISTS (SELECT 1
& && && && && && && && &&&FROM customers c
& && && && && && && && & WHERE c.cust_id = s.cust_id
& && && && && && && && && && & AND c.country_id = 'US'
& && && && && && && && &)
& && && && &);
这里的假定是在s.cust_id 列上可能有空值,而我们想要返回那些行。在Oracle 12c数据库之前,EXISTS子查询无法被展开,因为它出现在一个带有IS NULL谓词的OR谓词(析取谓词)中。因为无法被展开,导致不理想的计划被产生,子查询被作为过滤操作应用在SALES和PRODUCTS表的连接之后。
(图 31. Oracle 11g数据库的计划显示EXISTS 自查询被作为过滤操作应用于连接之后)
在Oracle 12c数据库中,一种新型的半连接被引入,称为接受空值的半连接。这种新连接扩展了半连接的算法,在连接的左边的表的连接列上检查空值。在这个例子中检查会发生在s.cust_id。如果列包含空值,那么相应的SALES表上的行被返回,否则半连接被执行以确定该行是否满足连接条件。接受空值的半连接计划如下图32所示。
(图32. Oracle 12c数据库的计划显示 EXISTS子查询被展开,在customers和sales之间使用了接受空值的半连接)
标量子查询的展开
标量子查询是出现在SQL语句的SELECT子句的子查询。因为标量子查询不能被展开,所以一个相关的标量子查询(它引用了子查询之外的列)必须为外层查询产生的每一行被取值。考虑下面的查询:
SELECT c.cust_id, c.cust_last_name, c.cust_city,
& && &(SELECT avg(s.quantity_sold)
& && && &FROM sales s
& && &&&WHERE s.cust_id = c.cust_id) avg_quan
FROM customers c
WHERE c.cust_credit_limit & 50000;
在Oracle 11g数据库中,对于CUSTOMERS 表中 CUST_CREDIT_LIMIT大于50000的每一行,在sales表上的标量子查询都必须被执行。SALES表是达标,扫描它很多次是非常耗费资源的。
(图 33.Oracle 11g数据库的计划显示,对于customers表返回的每一行,标量子查询都必须被取值)
将标量子查询展开并且将其转换为一个连接,就免除了为外层查询的每一行都进行求值的必要性。在Oracle 12c数据库中,标量子查询能够被展开,在这个例子中,SALES表上的标量子查询被转换成一个group-by视图。group-by视图确定会返回每组一行,正如标量子查询一样。查询中同样加入了一个外连接,这是为了确保即使当视图的结果为空时,CUSTOMERS的数据仍然会被返回。转换后的查询如下:
SELECT c.cust_id, c.cust_last_name, c.cust_city, v.avg_quan
FROM customers c,
& && &(SELECT avg(s.quantity_sold) avg_quan, s.cust_id
& && && &FROM sales s
& && & GROUP BY s.cust_id) v
WHERE c.cust_credit_limit & 50000
& && &AND c.cust_id = v.cust_id(+);
(图34. Oracle 12c数据库的计划显示标量子查询已经被展开成外连接和GROUP BY视图)
多表左外连接
在Oracle 12c数据库之前,如果在外连接的左边有多个表是不合法的,会导致ORA-01417错误。
(图 35. Oracle 11g数据库不支持多表左外连接)
执行这样一个查询的方法是将其翻译为ANSI语法。可是,实现这样的ANSI语法会导致一个横向视图被使用。Oracle无法合并横向视图,所以优化器的计划在连接顺序和连接方法上的选择就受到了限制,这可能导致不理想的计划。
(注:横向视图指的是这样的视图:它引用了不在视图中的表的列)
(图36. ANSI 语法导致带有横向视图的计划,它无法被合并,因此限制了连接顺序)
在Oracle 12c数据库,用Oracle的(+)语法指定的多表左外连接现已被支持。你也能够合并一个外连接的左边的多表视图。能够合并视图就能允许更多的连接顺序和连接方法被考虑,结果是更优的计划会被选中。
(图37. 对新的多表作连接的支持允许视图合并,并且会导致更优的计划)
初始化参数
有几个新的初始化参数可以管理Oracle 12c数据库的优化器及其新特性。下面是关于这些新参数的详细介绍。
OPTIMIZER_ADAPTIVE_FEATURES
对于新的自适应查询优化功能的使用,包括自适应连接,SQL计划指令的创建和使用,是受OPTIMIZER_ADAPTIVE_FEATURES参数控制的。这个参数的缺省值和OPTIMIZER_FEATURES_ENABLE(OFE)相关。如果OFE被设置为12.1.0.1或者更高,那么OPTIMIZER_ADAPTIVE_FEATURES被设为TRUE, 所有的自适应查询优化功能将会启用。如果OFE被设为比12.1.0.1更低,那么OPTIMIZER_ADAPTIVE_FEATURES将会被设为FALSE, 所有的自适应查询优化功能都不会启用。
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
乍一看,执行计划的自适应或者中途变动有些吓人。为了更好地理解多少SQL语句会受到新的自适应计划的影响,你可以将自适应计划开启为只报告模式,方法是将OPTIMIZER_ADAPTIVE_REPORTING_ONLY设置为TRUE(缺省值是FALSE)。在这个模式下,启用自适应连接方法所需的信息被收集,但是不会有任何修改计划的行动。这意味着缺省的计划总是会被使用,但计划在非报告模式下会如何调整的信息也会被收集。
OPTIMIZER_DYNAMIC_SAMPLING
虽然OPTIMIZER_DYNAMIC_SAMPLING参数不是新的,但它确实有了新的级别11, 这个级别控制动态统计信息的生成。当设置为级别11时,优化器会自动确定哪些语句会受益于动态统计信息,即使所有的对象已经有了统计信息。
对现有功能的强化
在Oracle 12c数据库的开发过程中,大量的时间是被花在改善现有的优化器特性和功能,使得它更易于获得最佳的统计信息,确保最优的执行计划被选中。这个章节将会详细描述对现有优化器以及输送给它的统计信息的各方面的强化。
SQL计划的管理
SQL计划的管理 (SPM)是Oracle 11g数据库中最受欢迎的优化器新特性之一,因为它确保性能不会因为执行计划的变动而下降。为了确保这一点,只有被接受的执行计划才会被使用;任何实际发生了的计划的演变都会被跟踪并且在随后的一个时间点进行评估,并且只有当新计划在运行时间上显示出可观的改善,才会被接受。SQL计划的管理有三个主要部件:
1. 计划的捕获:
SQL计划基线的创建,它们存储了所有相关的SQL语句的执行计划。SQL计划基线存储在SYSAUX表空间的SQL管理库中。
2. 计划的选择:
对于具备SQL计划基线的语句,确保仅有被接受的执行计划才会被使用,并且将为一个语句找到的新的执行计划,记录为未接受计划并存储在SQL计划基线中。
3. 计划的演变:
为一个给定的语句评估所有未接受计划,只有那些显示出性能改善的计划才会变成SQL计划基线中被接受的计划。
在Oracle 12c数据库中,SPM的计划演变已被强化,以允许计划的自动演变。
计划的自动演变是由SPM的演变顾问完成的。演变顾问是一项自动任务(SYS_AUTO_SPM_EVOLVE_TASK),它在夜晚的维护窗口进行操作,自动为SPM中的未接受计划执行演变过程。自动任务将所有SPM中的未接受计划排等级(新发现的计划排在最高级),然后在维护窗口关闭之前为尽可能多的计划执行演变过程。
所有那些未接受计划,如果性能比计划基线中现有的计划更好,则自动被接受。然而,如果未接受计划未能达到性能标准,则仍然保持为未接受状态,并且它们的 LAST_VERIFIED会被修改为当前时间戳。至少在30天内,自动任务不会试图将一个未接受计划再次进行演变, 在此之后也仅当SQL为激活状态(LAST_EXECUTED被修改过)才会演变。
夜间的演变任务的结果可以通过DBMS_SPM.REPORT_AUTO_EVOLVE_TASK函数查看。SPM演变顾问的任何方面都可以通过企业管理器或者PL/SQL包DBMS_AUTO_TASK_ADMIN进行管理。
此外,你也可以利用ORACLE企业管理器或者提供的DBMS_SPM包对未接受计划手动进行演变。从Oracle 12c开始,原有的SPM演变函数(DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE)被废弃,代之以新的调用演变顾问的API。图38展示了调用演变顾问的一系列步骤。典型的过程为三个步骤的处理,从演变任务的创建开始。每个任务都被给予一个唯一的名字,这使得它可以被多次执行。一旦任务被执行,你就可以查看演变报告,方法是为DBMS_SPM.REPORT_EVOLVE_TASK函数提供TASK_ID和EXEC_ID。
(图38. 手动调用演变顾问所需的步骤)
当演变顾问被手动调用,未接受的计划不会被自动接受,即使它达到了性能标准。计划必须使用DBMS_SPM.ACCEPT_SQL_PLAN_BASELINE 过程被手动接受。演变报告含有详细的指导信息,包括关于接受计划所需的特定的语法。
(图39. 手动接受一个SQL基线中的计划)
在原先,只有SQL语句的纲要(即outline, 是为了重现一个特定计划而必需的一套完整的提示集合)被捕获并作为SQL计划基线的一部分。从Oracle 12c数据库开始,当一个计划被添加到SQL计划基线,实际的执行计划也会被记录下来。对于那些在以前的版本被添加到SQL计划基线中的执行计划,当它们第一次在Oracle 12c数据库中被执行,实际的执行计划也会被添加到SQL计划基线中。
捕获实际执行计划是很重要的,这是为了确保一个SQL计划基线从一个系统被转移到另一系统时,SQL计划基线中的计划仍然能被显示,即使它所用到的某些对象或者解析模式本身在新系统中已经不存在了。注意,显示一个来自SQL计划基线中的计划,和能够重现这个计划,这是两件不同的事情。
对于SQL计划基线的任何计划,其详细的执行计划可以被显示,方法是在企业管理器的SQL计划基线页面点击计划的名称,或者使用DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE过程。图40显示了被接受的计划(SQL_PLAN_6zsnd8f6zsd9g54bc8843)的执行计划。所显示的计划,是当这个计划被添加到SQL计划基线所捕获到的实际计划,因为&plan rows&属性被设置为&From dictionary&(来自数据字典)。对于那些基于纲要而显示的计划,&plan rows&属性被设置为&From outline&(来自纲要)。
(图40. 显示来自SQL计划基线中的一个计划)
强化攻击信息
连同优化器统计信息这一领域的许多新功能一起,现有的统计信息收集技术也得到了几种强化。
增量统计信息
在分区表上收集统计信息,包括在表级(全局统计信息)和分区(子分区)级别的收集。如果一个分区表的INCREMENTAL属性被设为TRUE, DBMS_STATS.GATHER_*_STATS过程的GRANULARITY(粒度)参数包含GLOBAL,并且ESTIMATE_PERCENT被设为AUTO_SAMPLE_SIZE,那么ORACLE就会通过将分区级的统计信息进行聚合,精确地推导出所有全局级别的统计信息。
增量统计信息的工作原理是为表中的每个分区存储一份纲要(synopsis)。纲要是一种关于分区以及分区中的列的统计元数据。通过将每个分区的分区级统计信息及纲要进行聚合,可以精确地生成全局级别的统计信息,从而不必扫描整个表。
增量统计信息及其陈化(staleness)
在Oracle 11g数据库中,如果一张表的增量统计被打开,当其中的一个分区的一行数据被修改时,那个分区的统计信息就被认为已经过于陈旧,必需被重新收集才能用于生成全局级别的统计信息。
在Oracle 12c数据库中,一个称为INCREMENTAL_STALENESS的新属性允许你控制分区统计信息何时被认为已陈化,并且不能胜任生成全局统计信息。在缺省情况下,INCREMENTAL_STALENESS被设为NULL, 这意味着一旦有一行数据被修改,分区级统计就被认为已陈化(和11g相同)。
或者,它也可被设置为USE_STALE_PERCENT 或 USE_LOCKED_STATS。USE_STALE_PERCENT的意思是只要被修改行数的百分比低于STALE_PRECENTAGE属性的值(缺省是10%),分区级统计就会被使用。USE_LOCKED_STATS的意思是如果一个分区上的统计信息被锁定,就会被用于生成全局统计信息,不管这个分区中自从上次收集以来有多少行数据被修改。
增量统计信息以及分区交换加载
分区的好处之一是可以通过分区交换命令轻易地、迅速地加载数据,对业务用户造成最小的影响。分区交换命令允许一张非分区表中的数据被切换到分区表的指定分区中。这个命令并不会物理地移动数据;相反,它只是修改了数据字典,将指针从分区交换到表上,反之亦然。
在以前的版本中,在分区交换的操作过程中,你无法在非分区表上生成必要的统计信息。相反,统计信息只有在交换发生后才能被收集,这是为了确保全局统计信息能够被增量维护。
在Oracle 12c数据库中,必要的统计信息(纲要)可以在非分区表上创建,从而使得在分区交换中被交换的统计信息能够自动被用于增量维护全局统计信息。新的DBMS_STATS表属性INCREMENTAL_LEVEL可以被用来识别那些即将用于分区交换加载的非分区表。通过将INCREMENTAL_LEVEL设置为TABLE(缺省值是PARTITION),Oracle会在收集统计信息的时候自动为这张表创建一个纲要。这个表级的纲要,在交换加载结束后会变成分区级的纲要。
并发统计信息
在Oracle 11.2.0.2数据库中,统计信息的并发收集被引入。当全局统计信息的收集属性CONCURRENT被设置,Oracle会利用作业调度器和高级队列部件来为每一个对象(表或者分区)创建和管理一个并发的作业。
在Oracle 12c数据库中,统计信息的并发收集被强化以更好地利用每个调度的作业。如果一个表,或分区,或者子分区很小或者是空的,数据库可能自动将这个对象以及其他的小对象整批放进一个单独的作业来降低作业维护的开销。
通过将CONCURRENT选项设置为ALL或者AUTOMATIC,统计信息的并发收集现在可以被夜间统计信息收集作业所利用。新的ORA$AUTOTASK消费者群组被加入到资源管理器,在维护窗口期间被激活使用,以确保统计信息的并发收集不会占用太多的系统资源。
列群组的自动侦测
扩展统计信息有助于优化器改善SQL语句的基数估算的精确性,如果这个语句涉及到包含函数的列(例如UPPER(LastName)),或者在过滤谓词、连接条件、分组键中用到的来自同一个表的多个列。虽然扩展统计信息及其有用,但要得知何种扩展信息应该被创建是很困难的,如果你对应用或者数据集不熟悉的话。
列群组的自动侦测,会自动根据给定的工作负载确定一张表上需要哪些列群组。请注意这个功能不会为带有函数的列创建扩展统计信息,它只能用于列群组。列群组的自动侦测是一个简单的三步骤的过程:
1.发起列的使用情况
为了确定适当的列群组,Oracle必需对具有代表性的工作负载进行观察。工作负载可以在SQL优化集(SQL Tuning Set)中提供, 或者通过对允许中的系统进行监控而获得。新的过程DBMS_STATS.SEED_COL_USAGE应该被使用,它指明了工作负载,并且告诉Oracle应该对工作负载观察多长时间。下列例子为当前系统打开了5分钟或者300秒的监控。
(图41, 开启列群组的自动侦测)
监控过程记录不同的信息,来自于你在sys.col_usage$可看到的传统的列使用信息,并且把它存放在sys.col_group_usage$。对于在监控窗口过程中被执行或者解释的任何SQL, 这个信息都会被存储。一旦监控窗口结束,你就可以使用新函数DBMS_STATS.REPORT_COL_USAGE来查看为特定的一个表记录的列使用信息。这个函数产生一个报表,它列出了在工作负载中这个表的哪些列被用于过滤谓词,连接谓词和分组子句。你也可以运行DBMS_STATS.REPORT_COL_USAGE来查看特定模式下的所有表的报告,只需提供模式名称,并将表名设为NULL。
42. 查看列使用情况)
2.创建列群组
为每个表调用DBMS_STATS.CREATE_EXTENDED_STATS函数,它就会自动根据监控窗口过程中捕获到的列使用信息自动创建必要的列群组。一旦扩展信息被创建,不管什么时候表统计信息被收集,它们就会被自动维护。
此外,列群组也可被手动创建,方法是将群组指定为DBMS_STATS.CREATE_EXTENDED_STATS的第三个参数。
(图43. 创建自动侦测到的列群组)
3.再度收集统计信息
最后的步骤是在受影响的表上再度收集统计信息,使得新创建的列群组拥有为它们创建的统计信息。
(图44.每当统计信息被收集,列群组统计就会被自动维护)
优化器是Oracle数据库最吸引人的部件之一,这是因为它的复杂性。它的目的是为每个SQL语句确定最高效的执行计划。它是基于查询的结构,它所具有的可用的关于数据的统计信息,以及所有与优化器和执行相关的特性来作出这些决定的。在Oracle 12c数据库中,随着新的查询优化自适应方法的引入,还有对可用的统计信息的强化,优化器实现了一个巨大的飞跃。
新的查询优化自适应方法使得优化器能够对执行计划作出实时调整,并且发现能够导致更佳的统计信息的额外信息。利用这些信息,和已有的统计信息一起,能够使得优化器对环境有更多的了解,并且允许它每次都选择一个优化的执行计划。
如同以往,我们希望通过详细描述在这一版本中对优化器和统计信息的修改,围绕着它们的迷雾将会被去除,而这一知识将会使得你的升级过程更加顺利,先知先戒备,凡事预则立!

我要回帖

更多关于 oracle 12c和11g 的文章

 

随机推荐