/*
结论:方向键索引可以消除索引热块访问竞争,是一个很不错的技术,只能该技术只能用在等值查询,而不能用在范围查询。
以下是生产中的一个案例,有人讲索引建成了反向键索引,却忘记了该系统有大量范围查询,还在纠结为何范围查询用不到索引。
这是一个建索引考虑不周的例子。
*/
--这里说的是反向键索引的故事
drop table t purge;
create table t (id number,deal_date date,area_code number,nbr number,contents varchar2(4000));
set autotrace off
insert into t(id,deal_date,area_code,nbr,contents)
select rownum,
to_date( to_char(sysdate-365,'J')+TRUNC(DBMS_RANDOM.VALUE(0,700)),'J'),
ceil(dbms_random.value(590,599)),
ceil(dbms_random.value(18900000001,18999999999)),
rpad('*',400,'*')
from dual
connect by rownum <= 100000;
commit;
create index idx_t_id on t(id) reverse;
set linesize 1000
set autotrace off
select index_name,index_type from user_indexes where table_name='T';
INDEX_NAME INDEX_TYPE
------------------------------ -----------
IDX_T_ID NORMAL/REV
set autotrace traceonly
--以下语句缘何用不到索引。
select * from t where id=28;
执行计划
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 69 | 138K| 401 (0)| 00:00:05 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 69 | 138K| 401 (0)| 00:00:05 |
|* 2 | INDEX RANGE SCAN | IDX_T_ID | 486 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
--不过奇怪的是,缘何下列语句却用不到索引,索引去哪儿?
select * from t where id>=28 and id<=50;
执行计划
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 304 | 608K| 1709 (1)| 00:00:21 |
|* 1 | TABLE ACCESS FULL| T | 304 | 608K| 1709 (1)| 00:00:21 |
--------------------------------------------------------------------------
统计信息
------------------------------------------------------
0 recursive calls
0 db block gets
6303 consistent gets
0 physical reads
0 redo size
2263 bytes sent via SQL*Net to client
426 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
23 rows processed
--原因在于这个索引不是普通索引,是为了避免热块竞争而建立的反向键索引,根本不支持范围查询,只支持等值查询。