oracle 提供了在线重定义功能,可以把普通表转化为分区表,记录一下操作过程:
首先扩展必要的表空间,然后查看要操作的表是否可以进行分区:
[oracle@erpdevdb admin]$ sqlplus " / as sysdba"
SQL*Plus: Release 10.2.0.1.0 - Production on Fri Mar 26 18:50:12 2010
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining optionsSQL> alter database datafile 7 resize 12288m;
Database altered.
SQL> connect erp/erp
Connected.
SQL>
SQL> set timing on
SQL>
SQL> EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('ERP', 'BALANCE',dbms_redefinition.cons_use_pk);PL/SQL procedure successfully completed.
如果不能分区,这一步会报错,然后建立中间表,这里采取按year进行range分区,按month进行list子分区的方式:
SQL> create table P_BALANCE
2 (
3 ID INTEGER not null,
4 YEAR INTEGER not null,
5 MONTH INTEGER not null,
6 ACODE VARCHAR2(16) not null,
7 BCODE VARCHAR2(16) not null,
8 FCODE VARCHAR2(4) not null,
9 CCODE VARCHAR2(16) not null,
10 GCODE VARCHAR2(20) not null,
11 SCODE VARCHAR2(8) not null,
12 NCODE VARCHAR2(8) not null,
13 HCODE VARCHAR2(75) not null,
14 ICODE VARCHAR2(35) not null,
15 XCODE VARCHAR2(35) not null,
16 DCODE VARCHAR2(32) not null,
17 ECODE VARCHAR2(16) not null,
18 RMBDEBIT NUMBER(19,4),
19 RMBCREDIT NUMBER(19,4),
20 RMBBALANCE NUMBER(19,4),
21 FCYDEBIT NUMBER(19,4),
22 FCYCREDIT NUMBER(19,4),
23 FCYBALANCE NUMBER(19,4),
24 USDDEBIT NUMBER(19,4),
25 USDCREDIT NUMBER(19,4),
26 USDBALANCE NUMBER(19,4),
27 QTYDEBIT NUMBER(19,8),
28 QTYCREDIT NUMBER(19,8),
29 QTYBALANCE NUMBER(19,8),
30 QTXDEBIT NUMBER(19,4),
31 QTXCREDIT NUMBER(19,4),
32 QTXBALANCE NUMBER(19,4),
33 GATTR1 VARCHAR2(8) not null,
34 GATTR2 VARCHAR2(8) not null,
35 GATTR3 VARCHAR2(8) not null,
36 GATTR4 VARCHAR2(8) not null,
37 GATTR5 VARCHAR2(8) not null,
38 GATTR6 VARCHAR2(8) not null,
39 GATTR7 VARCHAR2(8) not null,
40 GATTR8 VARCHAR2(8) not null,
41 GATTR9 VARCHAR2(8) not null
42 )
43 PARTITION BY RANGE (YEAR)
44 SUBPARTITION BY LIST (MONTH)
45 SUBPARTITION TEMPLATE
46 (SUBPARTITION B0 VALUES (0),
47 SUBPARTITION B1 VALUES (1),
48 SUBPARTITION B2 VALUES (2),
49 SUBPARTITION B3 VALUES (3),
50 SUBPARTITION B4 VALUES (4),
51 SUBPARTITION B5 VALUES (5),
52 SUBPARTITION B6 VALUES (6),
53 SUBPARTITION B7 VALUES (7),
54 SUBPARTITION B8 VALUES (8),
55 SUBPARTITION B9 VALUES (9),
56 SUBPARTITION B10 VALUES (10),
57 SUBPARTITION B11 VALUES (11),
58 SUBPARTITION B12 VALUES (12))
59 (PARTITION B2005 VALUES LESS THAN (2005),
60 PARTITION B2006 VALUES LESS THAN (2006),
61 PARTITION B2007 VALUES LESS THAN (2007),
62 PARTITION B2008 VALUES LESS THAN (2008),
63 PARTITION B2009 VALUES LESS THAN (2009),
64 PARTITION B2010 VALUES LESS THAN (2010),
65 PARTITION B2011 VALUES LESS THAN (MAXVALUE))
66 tablespace ERP_CW
67 ;Table created.
Elapsed: 00:00:00.57
为中间表建立主键:
SQL> alter table P_BALANCE add constraint P_BALANCE_PRIMARYKEY primary key (ID);
Table altered.
Elapsed: 00:00:00.11
开始用重定义的方式进行分区:
SQL> EXEC DBMS_REDEFINITION.START_REDEF_TABLE('CNDERP', 'BALANCE', 'P_BALANCE');
PL/SQL procedure successfully completed.
Elapsed: 00:02:17.53
根据源表上的索引规则建立分区后的local 索引:
SQL> CREATE INDEX P_BALANCE_ID ON P_BALANCE(ID)
2 local
3 (
4 PARTITION B2005 TABLESPACE ERP_INDEX,
5 PARTITION B2006 TABLESPACE ERP_INDEX,
6 PARTITION B2007 TABLESPACE ERP_INDEX,
7 PARTITION B2008 TABLESPACE ERP_INDEX,
8 PARTITION B2009 TABLESPACE ERP_INDEX,
9 PARTITION B2010 TABLESPACE ERP_INDEX,
10 PARTITION B2011 TABLESPACE ERP_INDEX
11 )
12 ;
CREATE INDEX P_BALANCE_ID ON P_BALANCE(ID)
*
ERROR at line 1:
ORA-01408: such column list already indexedElapsed: 00:00:00.00
SQL> create index P_BALANCE_CCODE_ACODE_NY on P_BALANCE (CCODE, ACODE, YEAR, MONTH)
2 local
3 (
4 partition B2005 TABLESPACE ERP_INDEX,
5 partition B2006 TABLESPACE ERP_INDEX,
6 partition B2007 TABLESPACE ERP_INDEX,
7 partition B2008 TABLESPACE ERP_INDEX,
8 partition B2009 TABLESPACE ERP_INDEX,
9 partition B2010 TABLESPACE ERP_INDEX,
10 partition B2011 TABLESPACE ERP_INDEX
11 )
12 ;Index created.
Elapsed: 00:00:55.11
SQL> create index P_BALANCE_DCODE on P_BALANCE (DCODE)
2 local
3 (
4 partition B2005 TABLESPACE ERP_INDEX,
5 partition B2006 TABLESPACE ERP_INDEX,
6 partition B2007 TABLESPACE ERP_INDEX,
7 partition B2008 TABLESPACE ERP_INDEX,
8 partition B2009 TABLESPACE ERP_INDEX,
9 partition B2010 TABLESPACE ERP_INDEX,
10 partition B2011 TABLESPACE ERP_INDEX
11 )
12 ;Index created.
Elapsed: 00:00:41.85
SQL> create index P_BALANCE_YEAR_MONTH_BCODE on P_BALANCE (BCODE, ACODE, YEAR, MONTH)
2 local
3 (
4 partition B2005 TABLESPACE ERP_INDEX,
5 partition B2006 TABLESPACE ERP_INDEX,
6 partition B2007 TABLESPACE ERP_INDEX,
7 partition B2008 TABLESPACE ERP_INDEX,
8 partition B2009 TABLESPACE ERP_INDEX,
9 partition B2010 TABLESPACE ERP_INDEX,
10 partition B2011 TABLESPACE ERP_INDEX
11 )
12 ;Index created.
Elapsed: 00:00:57.70
SQL> create index P_BALANCE_bcode_acode on P_BALANCE (BCODE, ACODE)
2 local
3 (
4 partition B2005 TABLESPACE ERP_INDEX,
5 partition B2006 TABLESPACE ERP_INDEX,
6 partition B2007 TABLESPACE ERP_INDEX,
7 partition B2008 TABLESPACE ERP_INDEX,
8 partition B2009 TABLESPACE ERP_INDEX,
9 partition B2010 TABLESPACE ERP_INDEX,
10 partition B2011 TABLESPACE ERP_INDEX
11 )
12 ;Index created.
Elapsed: 00:00:49.30
如果有外键约束等其他条件也要在这里一并建立,分区完成后还要注意表上的序列也需要rebuild。
然后就可以完成在线分区了,要注意的是,这一步才完成实际的切换:
SQL> EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE('ERP', 'BALANCE', 'P_BALANCE');
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.66
如果在分区动作过程中业务DML操作很多,可以先同步一次再进行实际切换,这样会减少停滞的时间:
dbms_redefinition.sync_interim_table('ERP', 'BALANCE', 'P_BALANCE');
分区完成后,要重新收集统计信息,并行度根据cpu数量自己确定:
SQL>exec dbms_stats.gather_table_stats(ownname => 'erp',tabname => 'balance',cascade => TRUE,degree => 4);
PL/SQL procedure successfully completed.
这里也可以根据需要指定granularity参数,然后就可以删除中间表了:
SQL> drop table p_balance;
Table dropped.
分区常用的一些视图:user_tab_partitions,user_ind_partitions,dba_part_tables,dba_part_indexes等。