今天来详细说说Oracle的执行计划,所谓执行计划,就是在执行某条SQL之前作出的执行方案,或者说是执行路径。Oracle的优化器模式有两大类,一个是基于规则的(RBO:Rule Based Optimizer),一个是基于代价的优化器(CBO:Cost Based Optimizer):
又可细分为:
CHOOSE, RULE ,FIRST_ROWS ,ALL_ROWS
CHOOSE方式表示,如果查询的表存在统计信息,则基于代价来执行(FIRST_ROWS),否则使用基于规则的方式来执行这条SQL,即RULE。(PS:在10g中已经废除了RBO)
先来理解几个概念:(名词解释来自网络加上自己的理解)
行源(row source):返回符合条件的行的集合,或者多表关联,或者是单表查询返回的行数据。
谓词(Predicate):说的直白些,就是查询中的where条件
驱动表(Driving Table):又称外层表,概念用于嵌套表与hash连接中,一般指的是经过谓词条件过滤之后返回的行源较少的表。
被探查表(Probed Table):与上一概念相对的,叫内层表,一般为返回较多行源的表。
组合索引(Concatenated index):多列组成的索引,一般需要有先导列索引才能生效。如emp表的索引有create index ... on emp(col1,col2,col3);
那么先导列就是col1,要使用索引,需含有字段col1,如where col1=..或where col1=.. and col2=...而,where col2=..则不走索引。
几种访问数据的方法:
1.全表扫描(Full Table Scan):顾名思义,读取表中所有的行,可以通过设置数据库的db_block_multiblock_read_count参数来设定多块读取以提高全表扫描的效率,一般查询的数据超过表的5%-10%时,可以使用全表扫描。
2.rowid读取数据(Table Access by ROWID)
3.索引读取(Index Scan):索引已经排序过了的,所以如果通过索引查询的值还进行了排序,这里并不需要再次进行排序,提高了效率。索引扫描还分为:index unique scan,index range scan,index full scan,index fast full scan
表之间的连接经常涉及到以下几种类型:
嵌套循环连接(外层表作为驱动,每一行对内层表进行高效访问,所以一般驱动表的行源较小,内层表较大,但是可以通过索引高效访问)
排序-合并连接(对关联的两个行源先分别根据连接列进行排序,然后再进行连接。因为需要排序所以这种方法一般都很浪费资源,但是如果需要连接的行源已经排完序了,那么这种方法效率还是挺高的。用于非等值连接,关联列都有索引的情况,)
哈希连接(两个较大的行源进行连接时,能够有较好的效率,但是只可用于等值连接)