CBO基础概念

CBO基础概念

CBO:评估 I/O,CPU,网络(DBLINK)等消耗的资源成本得出html

1、cardinality

cardinality:集合中包含的记录数。实际CBO评估目标SQL执行具体步骤的记录数,cardinality和成本是相关的,cardinality越大,执行步骤中的成本就越大sql

2、Selectivity

Selectivity :谓词的过滤条件返回的结果的行数占未加谓词过滤条件的行数数据库

公式:=clip_image001[4]服务器

范围0-1,值越小,说明 选择性越好 返回的cardinality 越小;值越大,选择性越差,返回的cardinality 越大。网络

未加任何谓词条件结果集: original cardinality,增长谓词条件为:computed cardinality。oracle

computed cardinality=original cardinality*selectivityoop

在列上没有NULL或者直方图的状况下,selectivity取值优化

SELECTIVITY=clip_image002ui

NUM_DISTINCT :表示为列中不一样值的个数code

3、transitivity(可传递性)

CBO会对现有的sql语句作等价转换,谓词条件、字段链接


优化器基础概念

1、优化类型:RBO和CBO

(一)、RBO

RBO基于规则的优化器access paths优先级:

  • 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

注意在不违反如上优先级的前提下,如有2个优化级同样的索引可用,则RBO会选择晚建的那个索引, 解决方法是重建你想要让RBO使用的那个索引,或者使用CBO……..

(二)、optimizer_mode :优化器的模式

一、RULE:使用rbo的规则

二、CHOOSE:9i中默认值,SQL语句所有的对象中无统计信息,使用RBO,其余使用CBO

三、FIRST_ROWS_n(n=1,10,100,1000):CBO会把哪些可以最快响应速度返回的成本设置为很小的值

四、ALL_ROWS:oracle10g 之后的默认值,会使用CBO来解析SQL,计算各个执行路径中的成本值最佳的吞吐量(最小的I/O和CPU资源)


2、结果集

执行计划中row,CBO评估的cardinality


3、访问数据的方法

(一)、访问表的方法:全表扫描和rowid访问

全表扫描:从高水位线下所有数据块读取,DELETE不会降低高水位线

ROWID访问:经过物理存储地址直接访问,rowid是个伪列,可是他能快速的定位的数据文件、块、行

scott@GULL> select empno,rowid ,dbms_rowid.rowid_relative_fno(rowid)||'_'||dbms_rowid.rowid_block_number(rowid)||'_'||dbms_rowid.rowid_row_number(rowid) location_row from emp;

     EMPNO ROWID              LOCATION_ROW
---------- ------------------ ------------------------------
      7369 AAASZHAAEAAAACXAAA 4_151_0
      7499 AAASZHAAEAAAACXAAB 4_151_1
      7521 AAASZHAAEAAAACXAAC 4_151_2
      7566 AAASZHAAEAAAACXAAD 4_151_3
      7654 AAASZHAAEAAAACXAAE 4_151_4
      7698 AAASZHAAEAAAACXAAF 4_151_5
      7782 AAASZHAAEAAAACXAAG 4_151_6
      7788 AAASZHAAEAAAACXAAH 4_151_7
      7839 AAASZHAAEAAAACXAAI 4_151_8
      7844 AAASZHAAEAAAACXAAJ 4_151_9
      7876 AAASZHAAEAAAACXAAK 4_151_10
      7900 AAASZHAAEAAAACXAAL 4_151_11
      7902 AAASZHAAEAAAACXAAM 4_151_12
      7934 AAASZHAAEAAAACXAAN 4_151_13

(二)、索引访问

索引访问的成本:一部分时访问相关的B树索引的成本,另外一个成本是回表的成本(根据索引中的rowid)

一、索引惟一性扫描(index unique scan):创建是惟一索引,能创建惟一索引的必定要创建惟一索引

二、索引范围扫描(index range scan):谓词条件中>、<等

三、索引全扫描(index full scan):扫描目标索引中全部的块的全部索引行。从最左的叶子节点读到底,由于叶子是一个双向链表

  • 索引全扫描的执行结果是有有序的,而且是按照该索引的索引键值列来排序,这也意味走索引全扫描可以既达到排序的效果,又同时避免了对该索引的索引键值列的真正的排序操做。
  • 索引全扫描时有序的就决定了不可以并行执行,索引全扫描时单块读
  • oracle中能作索引全扫描的前提条件是目标索引至少有一个索引键值列的属性是NOT NULL

四、索引快速全扫描(INDEX FAST FULL SCAN)

索引全扫描相似,读取全部叶子块的索引行

与全索引扫描不一样点

  • 索引快速全扫描只适用于CBO
  • 索引快速全扫描可使用多块读,也能够并行执行
  • 索引快速全扫描的执行结果不必定是有序的

五、索引跳跃式扫描(INDEX SKIP SCAN)

适用复合B数索引,谓词中的过滤条件不是以索引前导列。

只是对前导列作distinct:如create index ind_1 ON emp(job,empno)

Select * from emp where empno=7499

若是job有两个CLERK,SALESMAN

等同的语句

Select * from emp where job='CLERK' AND empno=7499
UNION ALL
Select * from emp where job='SALESMAN' AND empno=7499
oracle中的索引跳跃式扫描仅仅适用那些目标索引前导列的distinct值数量较少、后续非前导列的可选择性又很是好的情形,由于索引跳跃式扫描的执行效率必定会随着目标索引前导列的distinct值数量的递增而递减

4、表链接

(一)、表链接顺序

无论目标SQL中有多少个表作表链接,ORACLE在实际执行都是先作两两作表链接,在依次执行这样的两两表链接过程,直到目标SQL中全部表都已经链接完毕。

表链接很重要的是驱动表(outer table)和被驱动表(inner table)。

(二)、表链接方法

  • 嵌套循环链接(nested loop)

     一、若是驱动表所对应的驱动结果集的记录数较少,同时在被驱动表的链接列上又存在惟一性索引(或者在被驱动表的链接列上存在选择性很好的非惟一性索引),那么此时使用嵌套循环链接的执行效率很是高。

     二、大表也能够做为驱动表,关键看大表的谓词条件是否能够把驱动表的结果集的数据量降低下来

  • 哈希链接(hash join)

     一、哈希链接不必定会排序,或者说大多数状况下都不须要排序

     二、哈希链接的驱动表所对应的链接列的可选择性应尽量好,由于这个可选择性会影响对应hash bucket中的记录数,而hash bucket中的记录数又会直接影响从该hash bucket中查询匹配记录的记录。若是一个hash bucket里所包含的记录数过多,则可能或严重下降所对应哈希链接的执行效率,此时典型的表现就是该哈希链接执行了不少时间都没有结束,数据库所在数据库服务器上的CPU占用率很高,但目标SQL所消耗的逻辑读却很低,由于此时大部分时间都耗费在了遍历上述Hash Bucket里的全部记录上,而遍历Hash Bucket里的记录这个动做发生在PGA的工做区里,因此不耗费逻辑读。

     三、哈希链接只适用于CBO,它也只能用于等值链接条件(即便是哈希反链接,Oracle实际上也是讲其转换成了等价的等值链接)。

     四、哈希链接很适合小表和大表之间作链接且链接结果集的记录数较多的情形,特别是在小表的链接列的可选择性很是好的状况下,这时候哈希链接的执行时间就能够近似看做和全表扫描那个大表所耗费的时间至关。

     五、当两个表作哈希链接时,若是在施加目标SQL中指定的谓词条件(若是有的话)后获得的数据量较小的那个结果集所对应的hash table、 可以彻底容纳在内存中(PGA的工做区),则此时的哈希链接的执行效率会很是高

  • 排序合并链接(merge jion)

    一、一般状况下,排序合并链接的执行效率会远不如哈希链接,但前者的使用范围更广,由于哈希链接一般只能用于等值链接条件,而排序合并链接还能用于其余链接条件(<,<=,>,>=)

    二、一般状况下,排序合并链接并不适合OLTP类型的系统,器本质缘由是由于对于OLTP类型的系统而言,排序很昂贵的操做,固然,若是能避免排序操做,那么即便是OLTP类型的系统,也仍是可使用排序合并链接的。

    三、排序合并链接并不存在驱动表的概念

  • 笛卡尔积链接(Cartesian join)

     一、无任何链接条件,在执行计划中有cartesian,一般来讲,有笛卡尔积,sql语句是有问题的

(三)、表链接的类型

一、内链接(Inner JOIN)

 
--使用=
select * from emp a , dept b  where a.deptno=b.deptno
--join
select * from emp a join dept b on a.deptno=b.deptno

二、外链接(outer join)

左链接--使用(+)
select * from emp a,dept b where a.deptno=b.deptno(+)
--使用left join
select * from emp a left outer join dept b on a.deptno=b.deptno

右链接
--使用(+)
select * from emp a,dept b where a.deptno(+)=b.deptno
--使用left join
select * from emp a right outer join dept b on a.deptno=b.deptno

外链接的驱动表以(+)对面的表,如以上左链接,驱动表为a,右链接的驱动表为b

三、反链接(anti join)

链接中not in、not exists 、<>

sql A:select * from emp a WHERE A.DEPTNO NOT  IN (SELECT DEPTNO FROM dept b where a.deptno=b.deptno)

sql B:select * from emp a WHERE NOT EXISTS (SELECT 1 FROM dept b where a.deptno=b.deptno)

sql C:select * from emp a WHERE A.DEPTNO <> all (SELECT DEPTNO FROM dept b where a.deptno=b.deptno)
 

四、半链接(semi join)

链接中用in,exists,any

select * from emp a WHERE A.DEPTNO   IN (SELECT DEPTNO FROM dept b where a.deptno=b.deptno)

select * from emp a WHERE  EXISTS (SELECT 1 FROM dept b where a.deptno=b.deptno)

select * from emp a WHERE A.DEPTNO =any(SELECT DEPTNO FROM dept b where a.deptno=b.deptno)
 

五、星形链接

在OLTP基本不会用到,在OLAP中用到

参考:崔华《基于ORACLE的SQL优化》

相关文章
相关标签/搜索