1,先举个例子:
--------------------------------------------------------------------------------
| Id? | Operation??????????????????????? | Name??????????????????? | Rows? | Byt
--------------------------------------------------------------------------------
|?? 0 | SELECT STATEMENT???????????????? |???????????????????????? |???? |
|?? 1 |? SORT AGGREGATE????????????????? |???????????????????????? |???? 1 |
|?? 2 |?? TABLE ACCESS BY INDEX ROWID??? | T_TASK_G??????? |???? 1 |
|?? 3 |??? INDEX RANGE SCAN????????????? | IX_TASK_SUP_S |???? 3 |
|?? 4 |? VIEW??????????????????????????? |???????????????????????? |???? 2 |? 21
|?? 5 |?? COUNT STOPKEY????????????????? |???????????????????????? |?????? |
|?? 6 |??? VIEW????????????????????????? |???????????????????????? |???? 2 |? 21
|?? 7 |???? SORT ORDER BY??????????????? |???????????????????????? |???? 2 |?? 4
|?? 8 |????? NESTED LOOPS??????????????? |???????????????????????? |???? 2 |?? 4
|?? 9 |?????? NESTED LOOPS?????????????? |???????????????????????? |???? 2 |?? 2
|? 10 |??????? TABLE ACCESS FULL???????? | T_B_QU???????????? |???? 2 |?? 2
|? 11 |??????? INDEX UNIQUE SCAN???????? | PK_T_B_ASSI |???? 1 |
|? 12 |?????? TABLE ACCESS BY INDEX ROWID| T_B_B???????????? |???? 1 |
|? 13 |??????? INDEX UNIQUE SCAN???????? | PK_T_B_B????????? |???? 1 |
--------------------------------------------------------------------------------
简单来讲,是从右到左,从上到下的原则。
从横向来看10、11、13都是在最右端,优先 级是一样的,这时候就需要看纵 向的。对于10和11的执 行顺序,是先执行步骤10,再执行步骤11,步骤9结束后,再和步骤12得到的 结果集做步骤8的nested loop操作。
?
2,基础概念
Card
是指计划中这一步所 处理的行数。
Cost
是指cbo中这一步所 耗费的资源,以单块读 的IO成 本来表示。
Bytes
是指cbo中这一步所处理所 有记录的字节数,是估算出 来的一组值。
Predicate(谓词)
一个查询中的WHERE限制条件
Probed Table(被探查表)
该表又称为内层表(INNER TABLE)。在我们从驱动表中得到具体 一行的数据后,在该表中寻找符合连接条件 的行。所以该表应当为 返回较大row source的表且相应的列上应该有索引,索引扫描的范 围越小,效率越高。
?
3,rowid
rowid是一个伪列,是系统自 己给加上的。对每个表都有一个rowid的伪列,但是表中并不物理存储ROWID列的值。不过你可以像使用其它列 那样使用它,但是不能删除该列,也不能对该列的值进行修改、插入。一旦一行数据插入数据库,则rowid在该行的生命周期内是唯一的,即即使该行产生行迁移,行的rowid也不会改变。也有例外的情况,在分区表中,如果对分区列的值进行修改,这一行的数据会从一个分区迁移到另一个分区,那么这行数据对应的rowid也会改变;表做shrink或者move的操作时,rowid也会改变。
rowid对访问一个表中的给定的行提供了最 快的访问方法,通过ROWID可以直接定位到相应的数据块上,然后将其读到内存。我们创建一个索引时,该索引不但存储索引列的值,而且也存储索引值所对应的行的ROWID,这样我们通过索引快 速找到相应行的ROWID后,通过该ROWID,就可以迅速将 数据查询出来。这也就是我们使用索引查询时,速度比较快的原因。
在ORACLE 8以前的版本中,ROWID由FILE、BLOCK、ROW NUMBER构成。随着oracle8中对象概念的扩展,ROWID发生了变化,ROWID由OBJECT、FILE、BLOCK、ROW NUMBER构成。利用DBMS_ROWID可以将rowid分解成上述的 各部分,也可以将上述的各部分组成一个有效的rowid。
4,resuive sql
有时为了执行用户发出的一个sql语句,Oracle必须 执行一些额外的语句,我们将这些额外的语句称之为‘recursive calls’或‘recursive SQL statements’。比如创建一个表,ORACLE总是隐含的发出一些recursive? SQL语句来修改数据字典信息如tab$等。当需要的数据字典 信息没有在共享内存中时,经常会发生Recursive calls,这些Recursive calls会将数 据字典信息从 硬盘读入内存中。用户不比关心这些recursive SQL语句的执行情况, ORACLE会自动的在内部执行这些语句。当然DML语句与SELECT、sql parse或者在执行过程中需要空间扩展都可能 引起recursive SQL。
5,row source
用在查询中,由上一操作返回的符合条件的行的集合,即可以是表的全部行数据的集合;也可以是表的部分行数据的集合;也可以为对上2个row source进行连接操作(如join连接)后得到的行数据集合。
6,driving table
该表又称为外层表(OUTER TABLE)。这个概念用于嵌套与HASH连接中。如果该row source返回较多的行数据,则对所有的后续操作有负面影响。一般说来,是应用查询的限制条件后,返回较少行源的表作为驱动表,所以如果一个大表在WHERE条件有有限制条件(如等值限制),则该大表作为驱动表也是合适的,所以并不是只有较小的表可以作为驱动表,正确说法应该为应用查询的限制条件后,返回较少行源的表作为驱动表。在执行计划中,应该为靠上的那个row source。
7,组合索引
组合索引就是由多个列构成的索引。在组合索引 中有一个重要的概念:引导列(leading column),创建组合索引 时最前面的列即为引导列。如
Create index idx_test on table_name(col1,col2,…);
当我们进行查询时可以使用”where col1 = ? ”,也可以使用”where col1 = ? and col2 = ?”,这样的限制条件都会使 用索引,但是”where col2 = ? ”查询就不会使用该索引。所以限制条件中包含先导列时,该限制条件才会使用该组合索引。
有些情况下,”where col2 = ? ”也会使用索引 ,使用的是index skip scan,col1的distinct值有N个,那么就相当于N个基于col2的查询的union。N这个值越大,union的个数就越多,index skip scan的效率就越低,所以大部分情况下,当我们看到执 行计划中出现index skip scan时,需要加以关注。
8,可选择性
比较一下列中唯一键的数量和表中的行数,就可以判 断该列的可选择性。如果该列的唯一键的数量/表中的行数”的 比值越接近1,则该列的可选择性越高,该列就越适合创建索引,同样索引的可选择性也越高。在可选择性高 的列上进行查询时,返回的数据就较少,比 较适合使用索引查询。