日期:2014-05-16  浏览次数:20387 次

Oracle分区之三:索引分区

分区索引分为本地(local index)索引和全局索引(global index)。对于local索引,每一个表分区对应一个索引分区,当表的分区发生变化时,索引的维护由Oracle自动进行。对于global索引,可以选择是否分区,而且索引的分区可以不与表分区相对应。当对分区进行维护操作时,通常会导致全局索引的INVALDED,必须在执行完操作后REBUILD。Oracle9i提供了UPDATE GLOBAL INDEXES语句,可以使在进行分区维护的同时重建全局索引其中本地索引又可以分为有前缀(prefix)的索引和无前缀(nonprefix)的索引。而全局索引目前只支持有前缀的索引。B树索引和位图索引都可以分区,但是HASH索引不可以被分区。位图索引必须是本地索引。下面就介绍本地索引以及全局索引各自的特点来说明区别;

一、本地索引特点:
1,本地索引一定是分区索引,分区键等同于表的分区键,分区数等同于表的分区说,一句话,本地索引的分区机制和表的分区机制一样。
2,如果本地索引的索引列以分区键开头,则称为前缀局部索引。
3,如果本地索引的列不是以分区键开头,或者不包含分区键列,则称为非前缀索引。
4,前缀和非前缀索引都可以支持索引分区消除,前提是查询的条件中包含索引分区键。
5,本地索引只支持分区内的唯一性,无法支持表上的唯一性,因此如果要用本地索引去给表做唯一性约束,则约束中必须要包括分区键列。
6,本地分区索引是对单个分区的,每个分区索引只指向一个表分区,全局索引则不然,一个分区索引能指向n个表分区,同时,一个表分区,也可能指向n个索引分区,对分区表中的某个分区做truncate或者move,shrink等,可能会影响到n个全局索引分区,正因为这点,本地分区索引具有更高的可用性。
7,位图索引只能为本地分区索引。
8,本地索引多应用于数据仓库环境中。
本地索引:创建了一个分区表后,如果需要在表上面创建索引,并且索引的分区机制和表的分区机制一样,那么这样的索引就叫做本地分区索引。本地索引是由ORACLE自动管理的,它分为有前缀的本地索引和无前缀的本地索引。什么叫有前缀的本地索引?有前缀的本地索引就是包含了分区键,并且将其作为引导列的索引。什么叫无前缀的本地索引?无前缀的本地索引就是没有将分区键的前导列作为索引的前导列的索引。下面举例说明:

create table test (id number,data varchar2(100))
partition by RANGE (id)
(
partition p1 values less than (10000) tablespace p1,
partition p2 values less than (20000) tablespace p2,
partition p3 values less than (maxvalue) tablespace p3
);

create or replace procedure proc1
as
begin
 for i in 1..100000
 loop
  execute immediate
  'INSERT INTO warecountd values(:x,:y)' USING i,to_char(i+1000000);
 end loop;
end;
/


SQL> exec proc1

PL/SQL procedure successfully completed.


create index i_id on test(id) local; 因为id是分区键,所以这样就创建了一个有前缀的本地索引。

SQL> select dbms_metadata.get_ddl('INDEX','I_ID','HR') index_name FROM DUAL; 

看系统的对索引的metadata
SQL> set long 1000000
SQL> select dbms_metadata.get_ddl('INDEX','I_ID','HR') index_name FROM DUAL;

INDEX_NAME
--------------------------------------------

  CREATE INDEX "HR"."I_ID" ON "HR"."TEST" ("ID")
  PCTFREE 10 INITRANS 2 MAXTRANS 255
  STORAGE(
  BUFFER_POOL DEFAULT) LOCAL
 (PARTITION "P1"
  PCTFREE 10 INITRANS 2 MAXTRANS 255
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "P1" ,
 PARTITION "P2"

INDEX_NAME
--------------------------------------------
  PCTFREE 10 INITRANS 2 MAXTRANS 255
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "P2" ,
 PARTITION "P3"
  PCTFREE 10 INITRANS 2 MAXTRANS 255
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "P3" )

当然你也可以用上面的语句创建index,也可以用下面的SQL语句创建:

SQL> drop index i_id;

Index dropped

SQL> CREATE INDEX "HR"."I_ID" ON "HR"."TEST" ("ID") LOCAL
 (PARTITION "P1" TABLESPACE "P1" , PARTITION "P2" TABLESPACE "P2" ,PARTITION "P3" TABLESPACE "P3" );

Index created

create index i_data on test(data) local;因为data不是分区键,所以这样就创建了一个无前缀的本地索引。


看系统的对索引的metadata
SQL> select dbms_metadata.get_ddl('INDEX','I_DATA','HR') index_name FROM DUAL;

INDEX_NAME
--------------------------------------------

  CREATE INDEX "HR"."I_DATA" ON "HR"."TEST" ("DATA")
  PCTFREE 10 INITRANS 2 MAXTRANS 255
  STORAGE(