反向建索引(一)

2014-11-24 17:08:10 · 作者: · 浏览: 0

今天是2014-01-20,本来打算将方向键索引和其他索引混为其他索引日志中的,但是还是感觉这部分内容太重要了。在此记录一下方向键索引笔记。

什么是方向键索引?

方向键索引也是B树索引的特例索引,它是按照数据字节反转排列的,其中也存在rowid和普通B树索引一样。如在一个表中一个字段rowid+123456 rowid+234567 这是普遍B树索引,那么方向键索引为:rowid+654321 rowid+765432。

方向键索引使用情况:

特别在oracle RAC中方向键索引更为常见。当一个表的字段为递增序列字段填充的,那么当进行insert数据的时候会将相邻的数据添加到相同的索引叶子节点块中,那么这个时候在并发高的情况下就会产生索引的热块征用,如果使用方向键索引,那么可以避免此类事情的发生。

对于热块的征用往往伴随着buffer busy wait event等待事件(read by other session)。对于是否因为序列产生的可以通过查看gv$enqueue_stat如果字段EQ_TYPE如果类型为SQ ENQUEUE那么往往说明存在征用序列情况,此时可以通过设置序列的cache 数目以及noorder属性来避免此类等待征用的发生。

另外,对于解决索引热块征用的方案为:将索引创建为散列分区全局索引,这也是首先考虑的方式,因为如果设置为方向键索引会对数据库的cpu使用性能存在略微的消耗。

再次,就是在sql语句中等值谓词条件中方向键索引可以提高很高的性能,但是不能进行索引范围扫描,因为这是方向键打散的结果,其次注意,在非等值谓词条件中,可能不会使用方向键索引。

序列创建语法:

create sequence sequence_name

[start with start]

[increment by increment]

[minvalue minvalue|nominvalue]

[mavalue maxvalue| nomaxvalue}

[cache cache| nocache]

[cycle |no cycle}

{order | noorder}

创建方向键索引;

创建方向键索引很简单就是使用reverse关键字:

eg:

SQL> create sequence emp_seq
  2  start with 1
  3  increment by 1
  4  minvalue 1
  5  nomaxvalue
  6  cache 100
  7  noorder;
SQL> 
SQL> create table emp_text(owner,object_name,object_type) as select owner,object_name,object_type from dba_objects;
SQL> commit;
SQL> insert into emp_text (owner,object_name,object_type)  select owner,object_name,object_type from dba_objects where rownum<10000;

9999 rows created.

SQL> commit;

Commit complete.

SQL> create sequence emp_seq
  2  start with 1
  3  increment by 1
  4  minvalue 1
  5  nomaxvalue
  6  cache 1000
  7  order;
create sequence emp_seq
                *
ERROR at line 1:
ORA-00955: name is already used by an existing object


SQL> drop sequence emp_seq;

Sequence dropped.

SQL> create sequence emp_seq
  2  start with 1
  3  increment by 1
  4  minvalue 1
  5  nomaxvalue
  6  cache 1000
  7  order;

Sequence created.

SQL> 
SQL> declare
  2    cursor emp_cursor is
  3      select * from emp_text for update;
  4    v_object_name emp_text%rowtype;
  5  begin
  6    open emp_cursor;
  loop
  7    8      fetch emp_cursor
  9        into v_object_name;
 10      if emp_cursor%found then
 11        update emp_text
 12           set object_id =
 13               (emp_seq.nextval)
 14         where object_name = v_object_name.object_name;
 15      end if;
 16      exit when emp_cursor%notfound;
 17    end loop;
 18    close emp_cursor;
 19  end;
 20  /

PL/SQL procedure successfully completed.

SQL> commit;

Commit complete.

SQL> select * from emp_text where rownum<10;

OWNER                          OBJECT_NAME                    OBJECT_TYPE                       OBJECT_ID
------------------------------ ------------------------------ ------------------------------ ------------
PUBLIC                         V$MAP_LIBRARY                  SYNONYM                                   1
SYS                            V_$MAP_FILE                    VIEW                                      2
PUBLIC                         V$MAP_FILE                     SYNONYM                                   3
SYS                            V_$MAP_FILE_EXTENT             VIEW                                      4
PUBLIC                         V$MAP_FILE_EXTENT              SYNONYM                                   5
SYS                            V_$MAP_ELEMENT                 VIEW                                      6
PUBLIC                         V$MAP_ELEMENT                  SYNONYM                                   7
SYS                            V_$MAP_EXT_ELEMENT             VIEW                                      8
PUBLIC                         V$MAP_EXT_ELEMENT              SYNONYM                                   9

9 rows selected.

SQL> 

创建方向键索引:

SQL> 
SQL> create index emp_text_reidx1 on emp_text(object_id) reverse;

Index created.

SQL> set autotrace trace exp
SQL> select * from emp_text where object_id=20;

Execution Plan
----------------------------------------------------------
Plan hash value: 2362949500

-----------------------------------------------------------------------------------------------
| Id  | Operation                   | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                 |     6 |   642 |    29   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP_TEXT        |     6 |   642 |    29   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | EMP_TEXT_REIDX1 |    42 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
----------------------