下面测试一下这句话的真实性:
hr@ORCL> create table t (id number,name varchar2(10)); hr@ORCL> create unique index ind_t on t (id); hr@ORCL> insert into t values(1,\'a\'); hr@ORCL> insert into t values(2,\'b\'); hr@ORCL> commit; hr@ORCL> set autot trace exp hr@ORCL> select * from t where id=1; Execution Plan ---------------------------------------------------------- Plan hash value: 1366100657 ------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 20 | 1 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 20 | 1 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | IND_T | 1 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------- hr@ORCL> drop index ind_t; hr@ORCL> create index ind_t on t (id,name); hr@ORCL> analyze index ind_t compute statistics; hr@ORCL> select * from t where id=1; Execution Plan ---------------------------------------------------------- Plan hash value: 3131770069 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 20 | 1 (0)| 00:00:01 | |* 1 | INDEX RANGE SCAN| IND_T | 1 | 20 | 1 (0)| 00:00:01 | --------------------------------------------------------------------------
㈡ INDEX FULL SCAN和 INDEX FAST FULL SCAN
在一句SQL中,如果我们想搜索的列都包含在索引里面的话
那么Index Full Scan 和 Index Fast Full Scan 都可以被采用代替Full Table Scan
有索引排序的时候,优化器可能会偏向于Index Full Scan
如果Select 列表中数据都可来自于索引中包含的字段,则通常容易选择Index Fast Full Scan
这样出来的数据是根据索引 的 extent 为单元,无顺序的
扫描block包含了所有枝节点,不区分是否叶子节点。可以做多块顺序扫描,一个io 包含多个block
Index Full Scan 是根据索引的叶子节点顺序获取叶子节点信息然后获得数据(通常还去表中获取数据)
这样出来的数据是有序的,并且除了定位第一个叶子节点走了根和枝节点block外
其他叶子节点只由上一个叶子节点的next 指针获得,这样一个索引叶子block就可产生一个io,是离散读
10g在Index Full Scan阶段就把不符合记录的数据先给过滤掉了,最后只有符合条件的rowid做回表
而9i下,Oracle就比较傻了,Index Full Scan的阶段实际上什么也没做
只是把所有的rowid都给得到,然后根据得到的rowid从表中取出数据,再过滤掉不符合条件的记录
INDEX_FFS使用多块读,所以在大部分时候,INDEX_FFS速度应该会比单块读的INDEX_FS要快
Index Full Scan将会按逻辑的顺序访问各个索引节点,结果集已经按照索引键值顺序排序,不需要单独排序
Index Fast Full Scan时索引块通过多块进行读取,结果集是无序的
所以,如果结果集需要排序那会使用INDEX_FS,如果结果集不需要排序则会使用INDEX_FFS
INDEX FULL SCAN
HINT写法:INDEX(表名 索引名)或者 INDEX_FS(表名 索引名)
原理:Oracle定位到索引的ROOT BLOCK,然后到BRANCH BLOCK(如果有的话),再定位到第一个LEAF BLOCK
然后根据LEAF BLOCK的双向链表顺序读取。它所读取的块都是有顺序的,也是经过排序的
INDEX FAST FULL SCAN
HINT写法:INDEX_FFS(表名 索引名)
原理:从段头开始,读取包含位图块,ROOT BLOCK,所有的BRANCH BLOCK,LEAF BLOCK
读取的顺序完全有物理存储位置决定,并采取多块读,每次读取DB_FILE_MULTIBLOCK_READ_COUNT个块
IFFS的成本计算公式是:
leaf_blocks/k (k依赖于db_file_multiblock_read_count,leaf_blocks依赖于索引统计信息)
查询某个表记录总数的时候,往往基于PRIMARY KEY的INDEX FAST FULL SCAN是最有效的
sys@ORCL> select index_name,blevel,leaf_blocks from user_indexes where table_name=upper(\'T\'); INDEX_NAME BLEVEL LEAF_BLOCKS ------------------------------ ---------- ----------- IDX_T 1 282
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26515977/viewspace-1207980/ ,如需转载,请注明出处,否则将追究法律责任。