ORACLE数据库SQL优化--->ORACLE访问数据的方法

目标SQL所需要访问的数据一般存储在表里,而ORACLE访问表中的数据有两种方法:一种是直接访问表,一种是先访问索引,在回表(当然,如果目标SQL所要访问的数据只通过访问相关的索引就可以得到,那么就不需要回表了)。

 

ORACLE访问表的方法:一种全表扫描,另一种是ROWID扫描。

全表扫描是指ORACLE在访问表的时候,会从该表所占用的第一个区(extent)的第一个块(block)开始扫描,一直扫描到该表的高水位线(HWM,HIGH WATER MARK),这段范围内所有的数据块ORACLE都要必须读到。当然,ORACLE会对这期间读到的所有数据施加目标SQL的WHERE条件中指定的过滤条件,最后返回只满足条件的数据。全表扫描可以用多块读的属性。

ROWID扫描时指ORACLE在访问目标表里的数据时,直接通过数据所在的ROWID去定位并访问这些数据。ROWID表示的是ORACLE中的数据行距离所在的物理存储地址,也就是说ROWID实际上是和ORACLE中数据块里的行记录一一对应。从严格意义上说,ORACLE中的ROWID扫描有两层含义:一种是用户在SQL语句中输入的ROWID的值直接去访问对应的数据行记录;另外一种是先去访问相关的索引,然后根据访问的索引得到的ROWID再回表去访问对应的数据行记录。

 

一,ROWID扫描

ROWID是ORACLE数据库里的一个伪列,在实际的表块中并不存在该列。下面我们来看一个使用ROWID伪列和DBMS_ROWID包实例。

 

SQL> set linesize 180
SQL> select employee_id,first_name,rowid,dbms_rowid.rowid_relative_fno(rowid) || '_' ||
dbms_rowid.rowid_block_number(rowid) || '_' || dbms_rowid.rowid_row_number(rowid)
location from emp_temp where manager_id=100;  2    3 

EMPLOYEE_ID FIRST_NAME           ROWID              LOCATION
----------- -------------------- ------------------ --------------------------------------------------------------------------------------------------------------------------
        201 Michael              AAAM0YAAEAAAAGEAAD 4_388_3
        101 Neena                AAAM0YAAEAAAAGEAAK 4_388_10
        102 Lex                  AAAM0YAAEAAAAGEAAL 4_388_11
        114 Den                  AAAM0YAAEAAAAGEAAX 4_388_23
        120 Matthew              AAAM0YAAEAAAAGEAAd 4_388_29
        121 Adam                 AAAM0YAAEAAAAGEAAe 4_388_30
        122 Payam                AAAM0YAAEAAAAGEAAf 4_388_31
        123 Shanta               AAAM0YAAEAAAAGEAAg 4_388_32
        124 Kevin                AAAM0YAAEAAAAGEAAh 4_388_33
        145 John                 AAAM0YAAEAAAAGEAA2 4_388_54
        146 Karen                AAAM0YAAEAAAAGEAA3 4_388_55
        147 Alberto              AAAM0YAAEAAAAGEAA4 4_388_56
        148 Gerald               AAAM0YAAEAAAAGEAA5 4_388_57
        149 Eleni                AAAM0YAAEAAAAGEAA6 4_388_58

14 rows selected.

 

从上面显示的内容可以看出,EMPLOYEE_ID=201的行记录所对应的ROWID伪列值是“AAAM0YAAEAAAAGEAAD” ,使用DBMS_ROWID包对该伪列翻译后的值是"4_388_3",这表示EMPLOYEE_ID为201的行记录实际物理存储地址位于4号文件第388个块的第3行记录。(注意数据块里行的记录时从记录号0开始算起的)。

上面的ROWID伪列的值可以直接在SQL语句的WHERE中使用如下:

SQL> select employee_id,first_name,rowid from emp_temp where rowid='AAAM0YAAEAAAAGEAAD';

EMPLOYEE_ID FIRST_NAME           ROWID
----------- -------------------- ------------------
        201 Michael              AAAM0YAAEAAAAGEAAD

 

二,访问索引的方法:

注意这里所说的索引是指B数索引,ORACLE的其他索引暂时不考虑。

在ORACLE里访问B树索引的操作都必须从根节点开始,即都会经历一个从根节点到分支块再到叶子块的过程。索引叶子块中包含被索引的键值和用于定位该索引键值所在的数据行在表中实际物理存储位置的ROWID。B树索引的结构决定了在ORACLE里通过B树索引访问数据的过程是先访问相关的B树索引,然后根据访问该索引后得到的ROWID再回表去访问对应的数据行记录(当然,如果目标SQL所要访问的数据只通过访问相关的索引就可以得到,那么就不需要回表了)。

1,索引唯一性扫描(INDEX UNIQUE SCAN)是针对唯一性索引(UNIQUE INDEX)的扫描,它仅仅适用于WHERE条件里是等值查询的目标SQL。因为扫描的对象时唯一性索引,所以唯一性扫描的结果之多只返回一条记录。

2,索引范围扫描(INDEX RANGE SCAN)

3,索引全扫描(INDEX FULL SCAN)适用于所有类型的B树索引,它是要扫描目标索引所有叶子块的所有索引行。这里需要注意的是,索引全扫描扫描目标索引的所有叶子块,但并不意味着要扫描该索引的所有分支块。索引全扫描执行的结果是有序的。默认情况下,索引全扫描的扫描结果的有序性决定了索引全扫描时不能够并行执行的,并且通常情况下索引全扫描使用的是单块读。

4,索引快速全扫描(INDEX FAST FULL SCAN)

它和索引全扫描很相似,他们之间有以下三点区别:

a, 索引快速全扫描只适用于CBO。

b,索引快速全扫描可以使用多块读,也可以并行执行

c,索引快速全扫描的执行结果不一定是有序的。这是因为索引快速全扫描时,ORACLE是根据索引行在磁盘的物理存储顺序来扫描,而不是根据索引行的逻辑顺序来扫描的,所以才不一定有序。

d, 索引跳跃式扫描(INDEX SKIP SCAN)

它使那些在WHERE条件中没有对目标索引的前导列指定查询条件但同时又对该索引的非前导列指定了查询条件的目标SQL依然可以用上该索引。

 

 


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值