目录
一、简介
二、全表扫描(TABLE ACCESS FULL)
三、通过ROWID访问表(TABLE ACCESS BY ROWID)
四、索引扫描(TABLE ACCESS BY INDEX SCAN)
五、参考资料
Oracle访问表中记录主要有下面三种方式:
下面结合示例分别对三种访问方式进行详解。
概念:Oracle顺序访问数据表中的每一条记录,并检查每条记录是否满足where指定的过滤条件。在表很大的情况下,不太建议使用全表扫描,效率很低,除非查询出来的记录数比较多(超过总量的5% -- 10%),才考虑使用全表扫描,否则全表扫描就是我们进行优化的一个关键点。
实现机制:ORACLE采用一次读入多个数据块(database block)的方式优化全表扫描,而不是只读取一个数据块,这极大的减少了I/O总次数,提高了系统的吞吐量,所以利用多块读的方法可以十分高效地实现全表扫描。
示例:
explain plan for select * from zhxg_xsxx_xsjbxx t where instr(t.XM,'张') > 0;
select * from table(dbms_xplan.display);
执行计划:
通过执行计划,可以看到上面访问zhxg_xsxx_xsjbxx的方式就是全表扫描TABLE ACCESS FULL,针对每条记录比较姓名中是否包含“张”。在日常工作中,我们要尽量减少全表扫描,在进行SQL优化的时候,全表扫描就是一个优化点,考虑是否能够增加一些索引来优化查询。
概念:ROWID是由Oracle自动加在表中每行最后的一列伪列,既然是伪列,就说明表中并不会物理存储ROWID的值;我们可以像使用其它列一样使用它,只是不能对该列的值进行增、删、改操作;一旦一行数据插入后,则其对应的ROWID在该行的生命周期内是唯一的,即使发生行迁移,该行的ROWID值也不变。每一个表都有一个ROWID列,一个ROWID值用于唯一确定数据库表中的的一条记录。ROWID表示了该行所在的数据文件、数据块以及行在该块中的位置,通过ROWID我们可以快速定位到目标数据上,通过ROWID访问是Oracle存取单行数据的最快方法。
通过ROWID访问表的这种方式又分为单个ROWID和多个ROWID两种情况:
单个ROWID示例:
--先查询出rowid
--select t.rowid,t.* from zhxg_xsxx_xsjbxx t;
explain plan for select t.rowid,t.* from zhxg_xsxx_xsjbxx t where t.rowid = 'AABUJXAACAAALCEAAA';
select * from table(dbms_xplan.display);
执行计划:
多个ROWID示例:
--先查询出多个rowid
--select t.rowid,t.* from zhxg_xsxx_xsjbxx t;
explain plan for select t.rowid,t.* from zhxg_xsxx_xsjbxx t where t.rowid in ('AABUJXAACAAALCEAAA', 'AABUJXAACAAALCEAAB','AABUJXAACAAALCEAAC');
select * from table(dbms_xplan.display);
执行计划:
可以看到,上面的执行计划中出现了INLIST ITERATOR,即INLIST迭代,该操作说明其子操作多次重复时,会出现该操作。迭代操作意味着条件中的对象列表一个接一个的迭代传递给子操作。
概念:通过索引查找到数据对应的rowid值(对于非唯一索引可能返回多个rowid值),然后根据rowid直接从表中得到具体的数据,这种查找方式称为索引扫描或索引查找(index lookup)。
实现机制:
索引扫描可以由2步组成:
Oracle中提供了五种索引扫描的方式:
关于索引扫描的详细介绍,之前有一篇文章已经详解介绍过了,可以参考这篇文章学习:https://blog.csdn.net/Weixiaohuai/article/details/106577668
更多关于Oracle数据表访问方式的文章,可以参考下面:
https://www.cnblogs.com/liuqiongliu/archive/2011/03/31/2000876.html
https://blog.csdn.net/leshami/article/details/7474308
https://www.cnblogs.com/xwdreamer/archive/2012/06/13/2547825.html