相关链接
一、查询优化器(Query Optimizer)
又叫优化器(Optimizer)。它是SQL分析和执行的优化工具,它负责生成、制定SQL的执行计划(Execution Plan)1。它在一定程度上决定了数据库的效率。
Oracle的优化器经历了以下两个阶段:
- RBO: Rule-Based Optimization 基于规则的优化器(根据 人积累下的经验 做出决策)。
- CBO: Cost-Based Optimization 基于代价的优化器(根据 数据分析结果=>收集统计信息 ,计算最小cost(成本),再做出决策, 10g起开始使用。
1.1 Syntax 语法
--查询优化器模式
SQL> show parameter optimizer_mode;
--修改优化器模式
SQL> alter session set optimizer_mode='XXX';
SQL> alter session set optimizer_mode='FIRST_ROWS';
SQL> alter session set optimizer_mode='FIRST_ROWS_10000';
SQL> alter session set optimizer_mode='ALL_ROWS';
1.2 Values 参数值
- first_rows_n
The optimizer uses a cost-based approach and optimizes with a goal of best response time to return the first n rows (where n = 1, 10, 100, 1000).
优化器使用基于成本(CBO)的方法,目标:响应时间最短,返回前n行(其中n = 1、10、100、1000)。 - first_rows
The optimizer uses a mix of costs and heuristics to find a best plan for fast delivery of the first few rows.
优化器混合使用基于成本(CBO)和规则(RBO)的方法,目标:快速找到前几行。 - all_rowsdefault
The optimizer uses a cost-based approach for all SQL statements in the session and optimizes with a goal of best throughput (minimum resource use to complete the entire statement).
优化器使用基于成本(CBO)的方法,目标:最佳吞吐量(完成整个语句所需的最少资源),最快速度返回全部结果。
all_rows 和 first_rows 的区别在于, all_rows 强调整体的执行效率,而 first_rows 强调最快返回前n条记录。
all_rows 在 OLAP 的数仓分析场景中比较多 - choose
RBO到CBO时代的过渡。如果SQL涉及的数据表中有一个有统计量,那么该SQL就是用CBO优化器。否则就是用RBO。
在9i版本曾是默认值。
动态采样技术是在CBO优化器前提下的技术方案。 - rule
基于规则通过解析SQL来决定扫描方式,不能通过表中数据进行判断。
Oracle 10g起,由于对数据不敏感,ORACLE已经彻底舍弃RBO。在优化器里面嵌入15种规则,根据Oralce指定的优先顺序规则,对指定的表进行执行计划的选择。
执行SQL语句符合哪种规则,就按照规则定制出相应的SQL执行计划。
比如在规则中,索引的优先级大于全表扫描;RBO是根据可用的访问路径以及访问路径等级来选择执行计划。
在RBO中,SQL写法会影响执行计划,要求开发人员非常了解RBO各项规则,导致菜鸟写出来的SQL脚本性能会非常差。
RBO Path 1: Single Row by Rowid
RBO Path 2: Single Row by Cluster Join
RBO Path 3: Single Row by Hash Cluster Key with Unique or Primary Key
RBO Path 4: Single Row by Unique or Primary Key
RBO Path 5: Clustered Join
RBO Path 6: Hash Cluster Key
RBO Path 7: Indexed Cluster Key
RBO Path 8: Composite Index
RBO Path 9: Single-Column Indexes
RBO Path 10: Bounded Range Search on Indexed Columns
RBO Path 11: Unbounded Range Search on Indexed Columns
RBO Path 12: Sort Merge Join
RBO Path 13: MAX or MIN of Indexed Column
RBO Path 14: ORDER BY on Indexed Column
RBO Path 15: Full Table Scan
二、CBO优化器
CBO是一种比RBO更加合理、可靠的优化器。从ORACLE 8中开始引入,9i中逐渐成熟。进入Oralce 10g后,查询优化器(Query Optimizer)将CBO作为默认优化器,并且Oralce官方不再支持RBO服务。
它的思路是通过获取 统计信息(Statistic)2,利用系统统计量进行各种执行路径试算,计算各种可能 执行计划(Explain Plan) 的 代价(cost),即COST,获取相对相对成本最低的执行计划,作为实际运行方案。
它依赖数据库对象的统计信息(Statistic),统计信息的准确与否会影响CBO做出最优的选择。如果对一次执行SQL时发现涉及对象(表、索引 等)没有被分析、统计过,那么Oracle会采用一种叫 动态采样(Dynamic Sampling)3 的技术。
2.1 组成
- 查询转换器(Query Transform)
- 等价改变查询语句的形式,产生更好的执行计划。它决定是否重写用户的查询(包括视图合并、谓词推进、非嵌套子查询*/子查询反嵌套、物化视图重写),以生成更好的查询计划。
- 代价评估器(Estimator)
- 通过复杂的算法、结合统计信息的三个值来评估各个执行计划的总体成本(cost):选择性(Selectivity)、基数(Cardinality)、成本(Cost)计划生成器会考虑可能的访问路径(Access Path)、关联方法和关联顺序,生成不同的执行计划,让计划生成器从这些计划中选择出执行代价最小的一个计划。
- 计划生成器(Plan Generator)
- 生成大量的执行计划,然后选择其总体代价或总体成本最低的一个执行计划。不同的访问路径(Access Path)、连接方式和连接顺序可以相互组合。
- 生成大量的执行计划,然后选择其总体代价或总体成本最低的一个执行计划。不同的访问路径(Access Path)、连接方式和连接顺序可以相互组合。
2.2 CBO可选参数
CBO优化器有两种可选的运行模式:
- first_rows 或 first_rows_n
- 【功能概述】:优先返回结果集中的前n条记录,而其他结果并不需要同时反馈,也就是说在处理数据的时候,后面的数据可能还没提取出来,前面的数据已经返回给用户了。
- 【适合场景】:网站分页功能,每次只需返回前n条,越靠前的页,显示结果需要的时间越短。
- 【注意事项】:排序使用的X列必须创建有索引,否则CBO会忽略 first_rows_n 而使用 all_rows.
- all_rows
- 【功能概述】:以最快的速度将SQL执行完毕,将结果集全部返回。
- 【适合场景】:数仓OLAP,需要获取全部数据进行分析。
- 【注意事项】:设置all_rows后需要注意shared pool问题,如果在当前会话期间重新获取统计信息可能会优先走shared pool进行软解析,不会按照最新的统计信息获取执行计划。
- 【功能对比】:all_rows 强调整体的执行效率,而 first_rows_n 强调以最快的速度返回前n条记录。
三、RBO缺点
既然RBO已经被CBO取代,RBO被弃用必然有不足之处
- RBO是通过oracle内部硬编码来对目标SQL选择合适的执行计划,换句话说此方法并没有考虑到目标表的实际数据量和数据分布(CBO通过直方图统计数据分布),也没有考虑到物理设备IO和服务器CPU等相关资源的等待和消耗,仅仅是根据自身的判断等级来判断SQL的执行计划。实际上并不适用所有的系统语句,一旦发生执行计划选择问题很难对其作出调整。
- RBO模式下对SQL的书写要求极高,甚至目标表出现的先后顺序不同都会出现不同的执行计划,这无异于对开发维护人员提出了更高的要求。
- RBO模式下10G以后版本的新特性都不能使用,例如统计信息(Statistic)、直方图(Histograms)、动态采样(Dynamic Sampling),这些新特性都给CBO选择最优的实际可行的执行计划带来了巨大的帮助。
RBO选错执行计划解决方式
- 对SQL中的 谓词4 条件做字符类型改变。假如一条SQL,我们需要查询一些数据,而走FULL SCAN的效率要高于INDEX RANG SCAN回表的效率,但是RBO模式下索引等级高于全表扫描等级,会用索引范围扫描,这是一个很糟糕的执行计划。我们可以通过修改索引列谓词的字符类型让这条SQL不走索引来提高效率。当然此类型改写方式多种多样,这里不再详细讨论。
- RBO中两个同等级的执行计划在数据字典中的缓存顺序也会影响实际的执行计划。在RBO中如果一条语句谓词中涉及两个索引,但是两个索引使用的先后顺序又严重影响SQL的执行效率。为了使SQL最先走IND_A,可对本来创建较早的IND_A进行重建。RBO会优先使用最新的索引。
- RBO中多表关联时,执行计划等级相同的表关联时,RBO 驱动表(OUTER TABLE)5选择是从右往左选择的,即最右侧的等级值表为驱动表。可以通过修改SQL文本中表的顺序来调整执行计划。注意:如果关联表的等级值不同,无论怎么调整SQL文本中表的顺序都不能改变执行计划。
- 通过hint来强制改变SQL的执行计划来达到理想的执行效率,这无异于是DBA的终极杀手锏。
- 【注意】:oracle中严格意义上是没有 驱动表(OUTER TABLE) 和 被驱动表(Probed Table)6 概念的,为了方便理解这里引用此概念。
20/09/11
M
执行计划(Execution Plan):
简单来说 执行计划(Execution Plan) 是Oracle在执行 SQL 时(10+ 在优化器是基于CBO的情况下)
会先查看 共享池(shared pool) 中找已有的 执行计划 (软解析)。
如果共享池中没有,则要通过 Analyze 或 DBMS 搜集好的 统计信息去生成执行计划。
如果连统计信息也没有,则会通过 动态采样(Dynamic Sampling) 按比例临时分析一部分数据,作为统计信息,生成执行计划。 ↩︎统计信息(Statistic):
描述数据库中表,索引的大小,规模,数据分布状况等的一类信息。比如,表的行数,块数,平均每行的大小,索引的leaf blocks,索引字段的行数,不同值的大小等,都属于 统计信息 。CBO正是根据这些 统计信息 数据,计算出不同访问路径下,不同JOIN方式下,各种计划的成本,最后选择出成本最小的计划。
可以通过 Analyze 和 DBSM 两种方式搜集统计信息。 ↩︎动态采样(Dynamic Sampling):
动态统计量收集是Oracle CBO优化器的一种特性。优化器生成执行计划是依据成本cost公式计算出的,如果相关数据表没有收集过统计量,又要使用CBO的机制,就会引起 动态采样 。
在生成执行计划时,以一个很小的采用率现进行统计量收集, 动态的收集表和索引上的一些数据信息。由于采样率低,采样过程快但是不精确,而且采样结果不会进入到数据字典中。 ↩︎谓词(Prediceate ):
一个查询中的WHERE限制条件或JOIN条件限制。在查看执行计划的信息中,经常会看到两个 谓词 filter 和 acces 。
● filter :表示 谓词 条件的值并不会影响数据访问路径,只起到过滤的作用。
● access :表示这个 谓词 条件的值将会影响数据的访问路径(表还是索引)。 ↩︎驱动表(OUTER TABLE):
驱动表 又称(OUTER TABLE)外层表。这个概念用于嵌套连接和HASH连接中,如果该row source返回较多的行数据,则对后续操作有负面影响。一般说来,应用查询条件的限制后,返回较少行源的表作为 驱动表 ,所以一个达标在where条件后返回较少数据,则大表也合适作为 驱动表,并不是只有较小的表可以作为 驱动表 。 ↩︎被驱动表(Probed Table):
该表通常被称作内层表(INNER TABLE)。从驱动表获取的具体一行的数据,需要在该表中寻找符合连接条件的行。所以数据量较大,且在相应连接列上有索引的表适合做为内层表。 ↩︎