您的位置:首页 > 数据库 > Oracle

Oracle中普通表转换为分区表常用的方法

2017-02-27 19:34 465 查看

在 Oracle 几年的学习中, 做了很多的实验,也遇到了很多的问题, 在这个过程中,积累了一些学习文档。 因为太多,不便于查阅。

根据自己对 Oracle 的理解以及日常工作中遇到的情况并进行了一些整理,方便自己的查看。 这些文档中有很多内引用借鉴了前辈们的资料和 google 上的

一些信息。  在这里引用的内容也是完全出于学习,没有其他用途,如有侵犯到版权的问题,请联系我。 我将删除这些信息。对数据库这块也是在不断的学习,

对 Oracle 的理解也是在不断的变化。 在这个过程中,难免有理解错误的地方, 或者内容上遗漏的,如果发现了问题, 烦邮件给我,我会虚心的学习,并更新该文档。

接下来我来通过实验方法将普通表转换成分区表。

1. Insert with a subquery method

2. Partition exchange method

3. Export/import method

1.插入: Insert with a subquery method

这种方法就是使用 insert 来实现。 当然在创建分区表的时候可以一起插入数据,也可以创建好后在insert 进去。

 这种方法采用DDL语句,不产生UNDO,

只产生少量 REDO,建表完成后数据已经在分布到各个分区中。

实验一:

create table interval_wjh

partition by range (hire_date)

interval ( numtoyminterval (1, 'month') )

(partition part1

values less than (to_date ('02/14/2012', 'mm/dd/yyyy')))

as

select id, time_fee from test_table;

2.交换分区 Partition exchange method

这种方法只是对数据字典中分区和表的定义进行了修改,没有数据的修改或

复制,效率最高。适用于包含大数据量的表转到分区表中的一个分区的操作。尽

量在闲时进行操作。

交换分区的操作步骤如下:

1. 创建分区表,假设有 2 个分区,P1,P2.

2. 创建表 A 存放 P1 规则的数据。

3. 创建表 B 存放 P2 规则的数据。

4. 用表 A 和 P1 分区交换, 把表 A 的数据放到到 P1 分区

5. 用表 B 和 p2 分区交换, 把表 B 的数据存放到 P2 分区

实验二:

创建分区表:
sql> create table P_p

2 (id number,time date)

3 partition by range(time)

4 (

5 partition p1 values less than (to_date('2012-08-12', 'yyyy-mm-dd')),

6 partition p2 values less than (to_date('2013-11-22', 'yyyy-mm-dd'))

7 );

表已创建。

创建 2 个分别对应分区的基表:
SQL> CREATE TABLE P_p1 as SELECT employee_id,hire_date FROM test_table WHERE

hire_date<TO_DATE('2010-09-1', 'YYYY-MM-DD');

表已创建。

CREATE TABLE P_p2 as SELECT employee_id,hire_date FROM test_table WHERE

time_fee<TO_DATE('2010-11-1', 'YYYY-MM-DD') and

time_fee>TO_DATE('2010-09-1', 'YYYY-MM-DD');

表已创建。

将2个基表与2个分区进行交换:
SQL> alter table P_p exchange partition p1 with table dba_p1;

表已更改。

SQL> alter table P_p exchange partition p2 with table dba_p2;

表已更改

分区表的其他操作

添加新的分区

添加新的分区有 2 中情况:

(1) 原分区里边界是 maxvalue 或者 default。 这种情况下,我们需要把边界分

区 drop 掉,加上新分区后,在添加上新的分区。 或者采用 split,对边界分区进

行拆分。

(2) 没有边界分区的。 这种情况下,直接添加分区就可以了。

以边界分区添加新分区示例:

(1) 分区表和索引的信息如下:

SQL> create table David
2 (
3 id varchar2(15 byte) not null,
4 areacode varchar2(4 byte)
5 )
6 partition by list (areacode)
7 (
8 partition t_list536 values ('536') tablespace TBS1,
9 partition p_other values (default)tablespace TBS2
10 );
表已创建。
SQL> create index David_id on David(id)
2 local (
3 partition t_list556 tablespace icd_service,
4 partition p_other tablespace icd_service
5 );
索引已创建。


(2) 插入几条测试数据:
SQL> insert into custaddr values('1','556');
已创建 1 行。
SQL> insert into custaddr values('2','551');
已创建 1 行。
SQL> insert into custaddr values('3','555');
已创建 1 行。
SQL> commit;
提交完成。

删除 default 分区

sql> alter table David drop partition p_other;

表已更改。

添加新分区

SQL> alter table David add partition t_list551 values('551') tablespace TBS1;

表已更改。

添加 default 分区

SQL> alter table David add partition p_other values (default) tablespace

TBS2;

表已更改。

select table_name,partition_name from user_tab_partitions where

table_name='DAVID';

TABLE_NAME PARTITION_NAME

------------------------------ ------------------------------

CUSTADDR T_LIST556

CUSTADDR T_LIST551

CUSTADDR P_OTHER

对于局部索引, oracle 会自动增加一个局部分区索引。验证一下:

sql> select owner,index_name,table_name,partitioning_type from dba_part_indexes

where index_name='ix_custaddr_id';

owner index_name table_name

icd ix_custaddr_id custaddr

sql> select index_owner,index_name,partition_name from dba_ind_partitions where

index_name='ix_custaddr_id';

index_owner index_name partition_name

------------------------------ ------------------------------ ------------------

icd ix_custaddr_id    p_other

icd ix_custaddr_id    t_list551

icd ix_custaddr_id    t_list556

split 分区拆分

在上节中,我们说明了可以使用 split 的方式来添加分区。 这里我们用 split

方法继续上面的实验。

sql> alter table david split partition p_other values('552') into (partition t_list552

tablespace TBS1, partition p_other tablespace TBS2);

表已更改。

注意:这里红色的地方,如果是 Range 类型的,使用 at, List 使用 Values。


SQL> select table_name,partition_name from user_tab_partitions where
table_name='DAVID';
TABLE_NAME PARTITION_NAME
-----------------
4000
------------- ------------------------------
CUSTADDR T_LIST556
CUSTADDR T_LIST551
CUSTADDR T_LIST552
CUSTADDR P_OTHER
SQL> select index_owner,index_name,partition_name from dba_ind_partitions
where index_name='DAVID_ID';
index_owner index_name partition_name
------------------------------ ------------------------------ ------------------
icd ix_custaddr_id p_other
icd ix_custaddr_id t_list551
icd ix_custaddr_id t_list552
icd ix_custaddr_id t_list556
注意:分区表会自动维护局部分区索引。全局索引会失效,需要进行 rebuild。

合并分区 Merge

相邻的分区可以 merge 为一个分区,新分区的下边界为原来边界值较低的分区,上边界为原来边界值较高的分区, 原先的局部索引相应也会合并,全局索引

会失效,需要 rebuild。

alter table custaddr merge partitions t_list552,p_other into partition p_other;

表已更改。

SQL> select index_owner,index_name,partition_name from dba_ind_partitions

where index_name='CUSTADDR_ID';

index_owner index_name partition_name

-------------------- ------------------------------ ------------------

icd custaddr_id p_other

icd custaddr_id t_list551

icd custaddr_id t_list556

SQL> select table_name,partition_name from user_tab_partitions where

table_name='CUSTADDR';

table_name partition_name

------------------------------ ------------------------------

david t_list556

david t_list551

david p_other

移动分区

SQL> alter table david move partition P_OTHER tablespace system;

表已更改。

SQL> alter table david move partition P_OTHER tablespace icd_service;

表已更改。

注意: 分区移动会自动维护局部分区索引, oracle 不会自动维护全局索引,所

以需要我们重新 rebuild 分区索引,具体需要 rebuild 哪些索引,可以通过

dba_part_indexes,dba_ind_partitions 去判断。

SQL> Select index_name,status From user_indexes Where

table_name='CUSTADDR';

INDEX_NAME STATUS

------------------------------ --------

IX_CUSTADDR_ID N/A

Truncate 分区

SQL> select * from david partition(T_LIST556);

ID AREA

--------------- ----

1 556

SQL> alter table david truncate partition(T_LIST556);

表被截断。

SQL> select * from david partition(T_LIST556);

未选定行

Truncate 相对 delete 操作很快,数据仓库中的大量数据的批量数据加载可能

会有用到; 截断分区同样会自动维护局部分区索引,同时会使全局索引 unusable,

需要重建

Drop 分区

alter table david drop partition T_LIST551;

表已更改。

SQL> select table_name,partition_name from user_tab_partitions where

table_name='DAVID';

TABLE_NAME PARTITION_NAME

------------------------------ ------------------------------

CUSTADDR T_LIST556

CUSTADDR P_OTHER

同样会自动维护局部分区索引,同时会使全局索引 unusable,需要重建

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  oracle 文档 SQL