实验环境如下:
SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production PL/SQL Release 11.2.0.4.0 - Production CORE 11.2.0.4.0 Production TNS for 64-bit Windows: Version 11.2.0.4.0 - Production NLSRTL Version 11.2.0.4.0 - Production
准备的测试表:
create table t(id integer,name varchar2(100));
insert into t
select rownum * 2 -1 as id, lengthb(dbms_random.string('a',50)) as name from dual connect by level<=100;
alter table t minimize records_per_block;
insert into t
select rownum * 2 as id, lengthb(dbms_random.string('a',50)) as name from dual connect by level<=100;
select id,dbms_rowid.rowid_block_number(rowid) from t;
commit;
create index idx_t_id on t(id);
第一次插入100条记录放到块1, 第二次插入100条记录到块2。 两个块之间的ID记录是相间隔的,目的是为了下面走索引时候最大限度的增加逻辑读。
PS:minimize 命令的作用是设定该表的所有块的记录数不超过存量的块的记录数。
SQL> select /*+rule*/ * from t where id<300;
已选择200行。
执行计划
----------------------------------------------------------
Plan hash value: 514881935
------------------------------------------------
| Id | Operation | Name |
------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| T |
|* 2 | INDEX RANGE SCAN | IDX_T_ID |
------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"<300)
Note
-----
- rule based optimizer used (consider using cbo)
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
215 consistent gets
0 physical reads
0 redo size
5350 bytes sent via SQL*Net to client
663 bytes received via SQL*Net from client
15 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
200 rows processed
这215次逻辑读,有200次是由访问T表的数据贡献的,剩余的15次是读取索引段的位图+访问索引段的块贡献的。
对比一下全表扫描的情况:
SQL> select * from t; 已选择200行。 执行计划 ---------------------------------------------------------- Plan hash value: 1601196873 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 200 | 13000 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| T | 200 | 13000 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement (level=2) 统计信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 21 consistent gets 0 physical reads 0 redo size 5350 bytes sent via SQL*Net to client 663 bytes received via SQL*Net from client 15 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 200 rows processed
全表扫描仅仅需要21次逻辑读,而索引访问却需要215次,远远高于前者。所以凡事无绝对,遇事要根据实际情况分析,实事求是。
PS: 全表扫描的这21次逻辑读,有约17次是读取表T的数据贡献的,虽然只有2个块有数据,但访问到高水位线+段头块,就已经有6个块了。
另外,这200条记录,每次载送15条(array size 参数决定的)后就返回一次给客户端,因此也会产生14次左右的逻辑读。
版权声明:本文为博主原创文章,未经博主允许不得转载。
全表扫描 索引 逻辑读



