RBO方式:
基于规则的优化方式
(Rule-Based Optimization
,简称为
RBO) ? 所以hint也不例外,除了其他的都是CBO优化方式 Rule:基于规则的方式。 PS: 优化模式是CHOOSE的情况下,看Cost参数是否有值来决定采用CBO还是RBO: PS的信息是从另外篇帖子里看到的,COST有值应该是指“有统计信息”的含义,暂时如此理解. ? Oracle如何配置默认的优化规则 B、Sessions级别通过ALTER SESSION SET OPTIMIZER_MODE=RULE/CHOOSE/FIRST_ROWS/ALL_ROWS来设定. C、语句级别用Hint()来设定 ? ? ? 没有使用HINT的执行计划如下: SELECT? EMPNO,ENAME,SAL FROM EMP WHERE EMPNO=7788; Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' 2? 1 INDEX (UNIQUE SCAN) OF 'PK_EMP' (UNIQUE) ? 1. Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' 2? 1 INDEX (UNIQUE SCAN) OF 'PK_EMP' (UNIQUE) ---------------------------------------------------------- ?0 SELECT STATEMENT Optimizer=HINT: FIRST_ROWS (Cost=1 Card=1 Bytes=33) ?1? 0? TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (Cost=1 Card=1 Bytes=33) ?2? 1? INDEX (RANGE SCAN) OF 'PK_EMP' (UNIQUE) (Cost=1 Card=1) Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=HINT: CHOOSE 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' 2? 1 INDEX (UNIQUE SCAN) OF 'PK_EMP' (UNIQUE) ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=HINT: RULE 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' 2? 1 INDEX (UNIQUE SCAN) OF 'PK_EMP' (UNIQUE) Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=33) 1? 0 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=1 Bytes=33) ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=94) 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (Cost=1 Card=1 Byte s=94) 2? 1 INDEX (RANGE SCAN) OF 'PK_EMP' (UNIQUE) (Cost=1 Card=1) Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE 1? 0 NESTED LOOPS 2? 1 TABLE ACCESS (FULL) OF 'EMP' 3? 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' 4? 3 INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE) 我在EMP表建立HIREDATE索引create index emp_date_idx on emp(hiredate); SQL> select * from emp e where e.hiredate=to_date('1987-04-19','yyyy-mm-dd') and e.empno=7788; Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' 2? 1 INDEX (UNIQUE SCAN) OF 'PK_EMP' (UNIQUE) 上面的查询语句同时使用了主键索引和日期索引,但是执行计划里并没有使用我建立日期的索引,因为采用基于效率的CBO模式,用EMPNO的UNIQUE索引效率高,下面强制使用日期索引进行查询得到的执行计划如下: SQL>select ? ?* ?from emp e where e.hiredate=to_date('1987-04-19','yyyy-mm-dd') and e.empno=7788; ? Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=87) 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (Cost=1 Card=1 Bytes=87) 2? 1? ?INDEX (RANGE SCAN) OF 'EMP_DATE_IDX' (NON-UNIQUE) (Cost=1 Card=1) Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE (Cost=826 Card=82 Bytes=7134) 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (Cost=826 Card=82 Bytes=7134) 2? 1 INDEX (FULL SCAN) OF 'PK_EMP' (UNIQUE) (Cost=26 Card=82) 对比下执行计划 SQL> select * from emp order by empno;(基于RBO的模式,理解有误?) Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' 2? 1 INDEX (FULL SCAN) OF 'PK_EMP' (UNIQUE) where e.hiredate>to_date('1980-04-19','yyyy-mm-dd'); Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=4 Bytes=88) 1? 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (Cost=1 Card=4 Bytes=88) 2? 1 INDEX (RANGE SCAN) OF 'EMP_DATE_IDX' (NON-UNIQUE) (Cost=2 Card=1) Execution Plan ---------------------------------------------------------- 0? SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=2 Bytes=174) 1? 0 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=2 Bytes=174)
? 优化器在分析SQL语句时,所遵循的是Oracle内部预定的一些规则。比如我们常见的,当一个where子句中的一列有索引时去走索引。
CBO方式:基于代价的优化方式(Cost-Based Optimization,简称为CBO)
它是看语句的代价(Cost),这里的代价主要指Cpu和内存。优化器在判断是否用这种方式时,主要参照的是表及索引的统计信息。统计信息给出表的大小、有少行、每行的长度等信息。这些统计信息起初在库内是没有的,是做analyze后才出现的,很多时候过期统计信息会令优化器做出一个错误的执行计划,因此应及时更新这些信息。
优化模式包括Rule、Choose、First rows、All rows四种方式:
Choose:默认的情况下Oracle用的便是这种方式。指的是当一个表或索引有统计信息,则走CBO的方式,如果表或索引没统计信息,表又不是特别的小,而且相应的列有索引时,那么就走索引,走RBO的方式。
SELECT STATEMENT [CHOOSE] Cost=1234--Cost有值,采用CBO
SELECT STATEMENT [CHOOSE] Cost= ?--Cost为空,采用RBO
?First Rows:它与Choose方式是类似的,所不同的是当一个表有统计信息时,它将是以最快的方式返回查询的最先的几行,从总体上减少了响应时间。
All Rows:也就是我们所说的Cost的方式,当一个表有统计信息时,它将以最快的方式返回表的所有的行,从总体上提高查询的吞吐量。没有统计信息则走RBO的方式
A、Instance级别我们可以通过在initSID.ora文件中设定OPTIMIZER_MODE=RULE/CHOOSE/FIRST_ROWS/ALL_ROWS如果没设定OPTIMIZER_MODE参数则默认用的是Choose方式。
为什么表的某个字段明明有索引,但执行计划却不走索引?
? 1、优化模式是all_rows的方式
? 2、表作过analyze,有统计信息
? 3、表很小,Oracle的优化器认为不值得走索引。
优化器提示 :不区分大小写, 多个提示用空格分开
如:select col1, col2 from tab1 where col1='xxx';
如果表使用了别名, 那么提示里也必须使用别名
如:select col1, col2 from tab1 t1 where col1='xxx';
如果使用同一个表的多个用,号分开
如: select col1, col2? from tab1 t1 where? col1='xxx';
表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化.
SELECT EMPNO,ENAME,SAL FROM EMP WHERE EMPNO=7788;
2.
表明对语句块选择基于开销的优化方法,并获得最佳响应时间,使资源消耗最小化.
SELECT EMPNO,ENAME,SAL FROM EMP WHERE EMPNO=7788;
Execution Plan
3.
表明如果数据字典中有访问表的统计信息,将基于开销的优化方法,并获得最佳的吞吐量;如果数据字典中没有访问表的统计信息,将基于规则开销的优化方法;
SELECT EMPNO,ENAME,SAL FROM EMP WHERE EMPNO=7788;
4.
表明对语句块选择基于规则的优化方法.
SELECT EMPNO,ENAME,SAL FROM EMP WHERE EMPNO=7788;
Execution Plan
5.
表明对表选择全局扫描的方法.
SELECT ?EMPNO,ENAME,SAL FROM EMP E WHERE EMPNO=7788;
6.
提示明确表明对指定表根据ROWID进行访问.
SELECT * FROM EMP WHERE ROWID>=' AAAHW7AABAAAMUiAAH' ?AND EMPNO=7788;
Execution Plan
7. (可能没有簇对象,暂且还没有使用和理解簇对象)
提示明确表明对指定表选择簇扫描的访问方法,它只对簇对象有效.
select e.empno ,d.dname from emp e,dept d? where e.deptno=d.deptno;
8.
表明对表选择索引的扫描方法. 指定使用表的某个索引:
9.
表明对表选择索引升序的扫描方法. (相当于ORDER BY 索引列 ASC)
SQL> SELECT? ?* ?FROM ?EMP;
10.
为指定表选择位图访问路经,如果INDEX_COMBINE中没有提供作为参数的索引,将选择出位图索引的布尔组合方式. (位图索引…搁置….)
11.
提示明确命令优化器使用索引作为访问路径.
SQL>SELECT ? SAL,HIREDATE FROM EMP E
12.
表明对表选择索引降序的扫描方法. (同9)
13.
对指定的表执行快速全索引扫描,而不是全表扫描的办法.
select * from emp where empno=7788;
14.
提示明确进行执行规划的选择,将几个单列索引的扫描合起来.
select * from emp e where empno=7788 and e.hiredate=to_date('1987-04-19','yyyy-mm-dd');
15.
对查询中的WHERE后面的OR条件进行转换为UNION ?ALL的组合查询. (懵懂啊,先存着)
例如:
select * from emp where deptno=10 OR empno=7788;
创客课程开发的每个主题课程需要基于现实情景,设置学习探究任务,通过问题研究、任务...
创客空间建设 能够给人们分享各种乐趣,通过电脑,技术,科学,艺术结合,设计创造一...
在了解创客教育之前,我们首先了解下何为创客。创客是一群喜欢或享受创新的人。创客跨...
STEAM教育是对传统教育的提升,它是基于自然学校方式的功能性框架,可以适合各类...