Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1109441
  • 博文数量: 227
  • 博客积分: 6860
  • 博客等级: 准将
  • 技术积分: 2688
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-02 16:06
文章分类

全部博文(227)

文章存档

2015年(7)

2014年(8)

2012年(5)

2011年(62)

2010年(145)

分类: Oracle

2010-09-09 12:01:08

建立实验表和索引

SQL> Create Table t(owner, object_name, subobject_name, object_id, data_object_id, object_type, created,

                                     last_ddl_time, timestamp, status, temporary, generated, secondary)
      Partition By Range(object_id)
        (Partition p_3000 Values Less Than(3000) Tablespace users,
         Partition p_6000 Values Less than(6000) Tablespace users,
         Partition p_max Values less than(maxvalue) tablespace users
         )
     As
     Select owner, object_name, subobject_name, object_id, data_object_id, object_type, created,
                    last_ddl_time, timestamp, status, temporary, generated, secondary
          From dba_objects;
SQL> create index idx_global_t_object_id on t(owner) global;
SQL> create index idx_local_t_object_id on t(object_id) local;


主要的分区维护操作

 

1.新增分区:如果分区边界不是maxvalue,那么可以直接add一个新的分区,如果边界是maxvalue,则需要先drop掉原有分区,然后再add,或者采用分区的拆分split
SQL> alter table t drop partition p_max;
Table altered
SQL> alter table t add partition p_9000 values less than(9000) tablespace users;
对于局部索引,oracle会自动增加一个局部分区索引。

 

2.移动分区
SQL> alter table t move partition p_6000 tablespace system;
Table altered
SQL> Select index_name,status From user_indexes Where table_name='T';
INDEX_NAME                    STATUS
------------------------------ --------
IDX_GLOBAL_T_OBJECT_ID        UNUSABLE
IDX_LOCAL_T_OBJECT_ID         N/A

分区移动会自动维护局部分区索引,oracle不会自动维护全局索引,所以需要我们重新rebuild分区索引,具体需要rebuild哪些索引,可以通过dba_part_indexes,dba_ind_partitions去判断。

 

3.截断分区
SQL> alter table t truncate partition p_3000 ;
Table truncated
SQL> Select index_name,status From user_indexes Where table_name='T';
INDEX_NAME                    STATUS
------------------------------ --------
IDX_GLOBAL_T_OBJECT_ID        UNUSABLE
IDX_LOCAL_T_OBJECT_ID         N/A

Truncate相对delete操作很快,数据仓库中的大量数据的批量数据加载可能会有用到;截断分区同样会自动维护局部分区索引,同时会使全局索引unusable,需要重建

 

4. Drop分区
SQL> alter table t drop partition p_6000;
Table altered
同样会自动维护局部分区索引,同时会使全局索引unusable,需要重建


5. 分区拆分split
通过user_tab_partitions视图来看table有哪些分区
SQL> Select table_name,partition_name From user_tab_partitions Where table_name='T';
TABLE_NAME                    PARTITION_NAME
------------------------------ ------------------------------
T                             P_3000
T                             P_9000
T                             P_MAX

现在想要把p_9000分区分成p_6000,用户存放object_id >=3000 and object_id<6000,p_9000用户存放object_id>=6000 and object_id<9000的记录,利用split技术,就可以实现

SQL> alter table tsplit partitionp_9000 at(6000) into (partitionp_6000 tablespace users,partitionp_9000 tablespace system);
SQL>
SQL> Select table_name,partition_name From user_tab_partitions Where table_name='T';
TABLE_NAME                    PARTITION_NAME
------------------------------ ------------------------------
T                             P_3000
T                             P_6000
T                             P_9000
T                             P_MAX

SQL> Select Max(object_id) ,Min(object_id) From t Partition (p_6000);
MAX(OBJECT_ID) MIN(OBJECT_ID)
-------------- --------------
         5999          3000

SQL> Select Max(object_id) ,Min(object_id) From t Partition (p_9000);
MAX(OBJECT_ID) MIN(OBJECT_ID)
-------------- --------------
         8999          6000

对于剧本索引IDX_LOCAL_T_OBJECT_ID,通过查看user_ind_partitions ,可以看到split后会自动一个局部分区索引,索引名字等同于新增分区的名字,全局索引会失效,需要rebuild。
 
6. 分区合并merge
 相邻的分区可以merge为一个分区,新分区的下边界为原来边界值较低的分区,上边界为原来边界值较高的分区,原先的局部索引相应也会合并,全局索引会失效,需要rebuild。

SQL> alter table t merge partitions p_6000,p_9000 into partition p_9000;
Table altered
SQL> Select table_name,partition_name From user_tab_partitions Where table_name='T';
TABLE_NAME                    PARTITION_NAME
------------------------------ ------------------------------
T                             P_3000
T                             P_9000
T                             P_MAX

SQL> Select Max(object_id) ,Min(object_id) From t Partition (p_9000);
MAX(OBJECT_ID) MIN(OBJECT_ID)
-------------- --------------
8999     3000

 

7. 分区交换exchange

分区的交换可以把一个表和分区表中的一个分区中的数据进行对换,分区的交换只是一个数据字典的操作,因此操作速度很快,对于数据仓库中的load阶段,因为已经做了数据的清洗动作,还可以用without validation来避免对表中数据的验证(需要全表扫描)

SQL> select count(*) from t partition(p_6000);
 COUNT(*)
----------
        0
SQL> create table t_6000 as select * from dba_objects where object_id>=3000 and object_id<6000;
SQL> alter table t exchange partition p_6000 with table t_6000;
SQL> select count(*) from t partition(p_6000);
 COUNT(*)
----------
     2955

SQL> select count(*) from t_6000;
 COUNT(*)
----------
        0

如果交换的表中包含的记录不符合分区的规定,那么可以用without validation子句跳过检查。

SQL> create table t_6000 as select * from dba_objects where object_id>=3000 and object_id<7000;
Table created

SQL> alter table t exchange partition p_6000 with table t_6000;
alter table t exchange partition p_6000 with table t_6000

ORA-14099:未对指定分区限定表中的所有行

SQL> alter table t exchange partition p_6000 with table t_6000 without validation;
Table altered


Exchange还有一个子句including indexes,指分区和表的索引相互交换,索引也可以交换,采用前面的例子,分区表有2个索引,一个在object_id列上的局部索引,一个是owner上的全局索引,实验在t_6000的object_id上建立所以,exchange可以完成,但在owner上,还是报错奥…

SQL>alter table t exchange partition p_6000 with table t_6000 including indexes without validation
ORA-14098: ALTER TABLE EXCHANGE PARTITION中的表索引不匹配

SQL> create index t_idx_object_owner on t_6000(owner);
建立所以后,交换成功。
SQL> drop index t_idx_object_id;
SQL> create index t_idx_object_owner on t_6000(owner);
SQL> alter table t exchange partition p_6000 with table t_6000 including indexes without validation ;
ORA-14098: ALTER TABLE EXCHANGE PARTITION中的表索引不匹配

 

添加分区实例

1.建表和相关索引

DROP TABLE SYSTEM.CUSTADDR CASCADE CONSTRAINTS;

CREATE TABLE SYSTEM.CUSTADDR
(
  ID         VARCHAR2(15 BYTE)                  NOT NULL,
  ADDRABB    VARCHAR2(100 BYTE)                 NOT NULL,
  TEAMID     VARCHAR2(20 BYTE),
  ADDRESS    VARCHAR2(150 BYTE),
  AREACODE   VARCHAR2(4 BYTE),
  ADDRONE    VARCHAR2(20 BYTE),
  ADDRTWO    VARCHAR2(20 BYTE),
  ADDRTHREE  VARCHAR2(100 BYTE),
  ADDRFOUR   VARCHAR2(100 BYTE),
  COMPABB    VARCHAR2(100 BYTE),
  CUSTID     VARCHAR2(15 BYTE)                  NOT NULL
)
TABLESPACE SYSTEM
PCTUSED    40
PCTFREE    10
INITRANS   1
MAXTRANS   255
LOGGING
PARTITION BY LIST (AREACODE)

  PARTITION T_LIST556 VALUES ('556')
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTUSED    40
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS  1
                BUFFER_POOL      DEFAULT
               ), 
   PARTITION P_OTHER VALUES (DEFAULT)
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTUSED    40
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS  1
                BUFFER_POOL      DEFAULT
               )
)
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


CREATE INDEX SYSTEM.IX_CUSTADDR_ADDRABB_TP ON SYSTEM.CUSTADDR
(ADDRABB)
  INITRANS   2
  MAXTRANS   255
LOCAL ( 
  PARTITION T_LIST556
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTFREE    10
    INITRANS   2
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS  1
                BUFFER_POOL      DEFAULT
               ), 
  PARTITION P_OTHER
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTFREE    10
    INITRANS   2
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS  1
                BUFFER_POOL      DEFAULT
               )
)
NOPARALLEL;


2. 添加新的分区

ALTER TABLE CUSTADDR DROP PARTITION P_OTHER;

ALTER TABLE CUSTADDR ADD PARTITION T_LIST558 VALUES ('558')
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTUSED    40
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS  1
                BUFFER_POOL      DEFAULT
               );

 ALTER TABLE CUSTADDR ADD PARTITION P_OTHER VALUES (DEFAULT)
    LOGGING
    NOCOMPRESS
    TABLESPACE SYSTEM
    PCTUSED    40
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                FREELISTS        1
                FREELIST GROUPS  1
                BUFFER_POOL      DEFAULT
               );

3. 重建分区索引

对于local索引,每一个表分区对应一个索引分区,当表的分区发生变化时,索引的维护由Oracle自动进行。对于global索引,可以选择是否分区,而且索引的分区可以不与表分区相对应。当对分区进行维护操作时,通常会导致全局索引的INVALDED,必须在执行完操作后 REBUILD。

分区索引是不能整体重建的,不能用
SQL>alter index loc_xxxx_col rebuild;

可以指定分区进行重建:
SQL>alter index loc_xxxx_col rebuild partition 分区名 online;
使用online来尽可能减少创建过程中出现的任何加锁问题。

如果你要整体新建,必须先drop 原有分区索引,然后
SQL>create index loc_xxxx_col on xxxx(col) local tablespace SYSTEM;
这是一个代价比较大的操作,要求有较大的临时表空间和排序区

阅读(2795) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~