1 问题背景
今天在check当前的数据库设计时,发现有两张表的数据可能会有较大数量的记录。而这两张表都是属于普通的数据表,按照当前的业务处理,随着表中的数据增加,对表中数据的查询势必会存在一定的效率问题,所以想着要把这两张表转换成分区表。
2 解决方案
从oracle9i开始,oracle就提供了在线重定义表的功能。通过调用dbms_redefinition包实现整个在线重定义。
详细使用步骤如下:
(1) 定义一张普通表:
CREATE TABLE t_test(a NUMBERPRIMARYKEY,b VARCHAR2(50));
(2) 向表中插入1000000条数据:
DECLARE
i NUMBER;
v_num NUMBER;
BEGIN
v_num := 10000;
FOR i IN1..1000000 LOOP
INSERTINTO t_Test(a,b) VALUES(i,'test_redefine');
IF( 0 = mod(i,v_num))THEN
COMMIT;
ENDIF;
ENDLOOP;
COMMIT;
END;
(3) 建立一个和原表一样的分区表,作为中间表。
CREATETABLE t_test_partition(a NUMBERPRIMARYKEY,b VARCHAR2(50))
PARTITIONBYHash(a)
PARTITIONS32;
(4) 调用dbms_redefinition包执行表的在线重定义。
EXEC DBMS_REDEFINITION.start_redef_table('DBSYAN','T_TEST','T_TEST_PARTITION');
(5) 将中间表中的数据和原始表中的数据进行同步操作。这一步不是必须的,如果在执行dbms_redefinition.start_redef_table和dbms_redefinition.finish_redef_table之间有大量的DML操作发生,那么执行一次dbms_redefinition.sync_interim_table来减少最后一步执行dbms_redefinition.finish_redef_table时的锁定时间。
EXEC dbms_redefinition.sync_interim_table('DBSYAN','T_TEST','T_TEST_PARTITION');
(6) 结束在线重定义过程
EXEC dbms_redefinition.finish_redef_table('DBSYAN','T_TEST','T_TEST_PARTITION');
注:
a) 如果原始的普通表不存在主键,在进行上面的第(4)步时会出错,所以在执行在线重定义前需保证原始表的主键是存在的;
b) 如果在执行在线重定义的过程中出现任何的失败操作,那么需要执行dbms_redefinition.abort_redef_table来回退;
c) 在执行完成上面的在线重定义之后,其实还有一些工作是没有完成的,比如需要给新建的分区表建立索引;
d) 在线重定义不是将普通表转换成分区表的唯一途径,这个还取决于业务需求。比如说在不考虑数据一致性的情形下,直接创建一个和普通表相对应的分区表,然后直接将原表中的数据拷贝过来就OK;
e) 上面的操作本身并不复杂,关键在于有这样一个概念。
上文只是在oracle 10g环境下做了在线重定义后的一个小记,以备后续查看