需求:
mx表,最早创建时间是2013-01-15。从2013-01-15到2013-02-27(总共的),有1500万数据。从2013-01-15到2013-01-31(2月份之前的)有560万数据。
由于mx表是主要业务表,数据量不能太大,所以需要半个月进行一次数据迁移,将数据“剪切”进mxbak表。
现在将mxbak表,按 创建时间 半月进行一个分区建立分区表。由于现在是2013-02-28,所以暂且只将2月份之前的数据(560万)迁移到mxbak,2月份以后的(1000万)数据还是先留在mx。
步骤:
--查看某表的分区:
select * from DBA_TAB_PARTITIONS where table_name='T_BUSI_PRESEND_MX_BAK'
select table_owner,table_name,partition_name,num_rows,blocks,avg_row_len,sample_size from DBA_TAB_PARTITIONS
where table_name='T_BUSI_PRESEND_MX_BAK'
--查看oracle表的分区信息
http://blog.163.com/zsq303288862@126/blog/static/937459612011649234186/
--1.查询mx表表结构,用于建立mxbak分区表(注意此处表的字段顺序应该相同,否则后面从mx取数据插入mxbak时,会报数据类型错误。所以下面的语句是字段经过排序后的结果)
select wm_concat(COLUMN_NAME||' '||data_type||'('||DATA_LENGTH||')') from (
select a.*
from all_tab_columns a
where a.OWNER = 'YDSOFT_YUXINGCHINASMS'
and a.TABLE_NAME = 'T_BUSI_PRESEND_MX'
order by a.column_id)
--2.新建分区表t_busi_presend_mx_bak,设定了maxvalue(注意设定maxvalue后不能用 add partition增加分区,要用split,后面会介绍)
CREATE TABLE t_busi_presend_mx_bak(ID VARCHAR2(20),MAINID VARCHAR2(20),SMSCONTENT VARCHAR2(1000),MOBILECODE VARCHAR2(22),CODETYPE VARCHAR2(10),CJR VARCHAR2(20),PRETONGDAOID VARCHAR2(20),CLIENTID VARCHAR2(20),SHR VARCHAR2(20),PRESENDTIME DATE,CJSJ DATE,SHSTATUS CHAR(1),SHSJ DATE,SENDSTATUS CHAR(1),SENDTYPE CHAR(1),SJTONGDAOID VARCHAR2(20),DXLX CHAR(1),REALTIME DATE,MSGLEVEL NUMBER(22),SJSENDSTATUS VARCHAR2(50),RET VARCHAR2(20),RPTTIME DATE,SESSIONID VARCHAR2(4000),WGID VARCHAR2(21),RESENDCNT NUMBER(22),JFCNT NUMBER(22),PUSHSTATUS CHAR(1),PUSHCOUNT NUMBER(22),PUSHTIME DATE)
PARTITION BY RANGE(cjsj)
(
PARTITION p_mxbak1_2 VALUES LESS THAN(TO_DATE('2013-01-31 23:59:59','yyyy-mm-dd hh24:mi:ss')) TABLESPACE TBS_YXKJ_DATA,
PARTITION p_mxbak2_1 VALUES LESS THAN(TO_DATE('2013-02-15 23:59:59','yyyy-mm-dd hh24:mi:ss')) TABLESPACE TBS_YXKJ_DATA,
PARTITION p_mxbak2_2 VALUES LESS THAN(TO_DATE('2013-02-28 23:59:59','yyyy-mm-dd hh24:mi:ss')) TABLESPACE TBS_YXKJ_DATA,
PARTITION p_mxbak_max VALUES LESS THAN (MAXVALUE)TABLESPACE TBS_YXKJ_DATA
);
--3.将mx表中1月份的数据插入mxbak表(开并行):
--close logging
alter table t_busi_presend_mx_bak nologging;
--set session parallel DML
alter session enable parallel dml;
--4:将数据导入新表中
INSERT /*+ APPEND PARALLEL( t_busi_presend_mx_bak,3) */ INTO t_busi_presend_mx_tmp SELECT /*+ PARALLEL(t_busi_presend_mx,3) */
T.*
FROM t_busi_presend_mx T where T.cjsj<=to_date('2013-01-31 23:59:59','yyyy-mm-dd hh24:mi:ss') ;
COMMIT;
--上面一切都没问题,可是,后来我又错误的将mx表中2月份之后的数据插入到mxbak表了,所以此时mxbak表前3个分区都有数据了,并且p_mxbak2_2分区数据是不完整的因为2月份还没过完。于是我准备将分区p_mxbak2_1,p_mxbak2_2删掉然后重建(因为有1000万数据,直接删分区比较快)。
--5.删除分区
Alter table t_busi_presend_mx_bak drop partition p_mxbak2_1;
Alter table t_busi_presend_mx_bak drop partition p_mxbak2_2;
--6.新建分区(报错)
Alter table t_busi_presend_mx_bak add partition p_mxbak2_1 VALUES LESS THAN(TO_DATE('2013-02-15 23:59:59','yyyy-mm-dd hh24:mi:ss')) TABLESPACE TBS_YXKJ_DATA;
由于建mxbak分区表时,定义了maxvalue,所以新增分区时,需要用split来建:
split 操作也类似:
alter table t_busi_presend_mx_bak split partition p_mxbak_max at(TO_DATE('2013-02-15 23:59:59','yyyy-mm-dd hh24:mi:ss')) into(
partition p_mxbak2_1 tablespace TBS_YXKJ_DATA,partition p_mxbak_max tablespace TBS_YXKJ_DATA
);
alter table t_busi_presend_mx_bak split partition p_mxbak_max at(TO_DATE('2013-02-28 23:59:59','yyyy-mm-dd hh24:mi:ss')) into(
partition p_mxbak2_2 tablespace TBS_YXKJ_DATA,partition p_mxbak_max tablespace TBS_YXKJ_DATA
);
--7.修改分区所在的表空间
--7.1创建备份表空间
create tablespace tbs_yxkj_bak datafile
'e:\oradata\orclyxkj\tbs_yxkj_bak01.dbf' size 4096m autoextend off,
'e:\oradata\orclyxkj\tbs_yxkj_bak02.dbf' size 4096m autoextend off,
'e:\oradata\orclyxkj\tbs_yxkj_bak03.dbf' size 4096m autoextend off,
'e:\oradata\orclyxkj\tbs_yxkj_bak04.dbf' size 4096m autoextend off,
'e:\oradata\orclyxkj\tbs_yxkj_bak05.dbf' size 4096m autoextend off,
'e:\oradata\orclyxkj\tbs_yxkj_bak06.dbf' size 4096m autoextend off,
'e:\oradata\orclyxkj\tbs_yxkj_bak07.dbf' size 4096m autoextend off
EXTENT MANAGEMENT LOCAL AUTOALLOCATE;
--7.2更改分区所在的表空间
alter table T_BUSI_PRESEND_MX_BAK move partition p_mxbak1_2 tablespace tbs_yxkj_bak;
alter table T_BUSI_PRESEND_MX_BAK move partition p_mxbak2_1 tablespace tbs_yxkj_bak;
alter table T_BUSI_PRESEND_MX_BAK move partition p_mxbak2_2 tablespace tbs_yxkj_bak;
alter table T_BUSI_PRESEND_MX_BAK move partition p_mxbak_max tablespace tbs_yxkj_bak;
分区索引和全局索引:
分区索引就是在所有每个区上单独创建索引,它能自动维护,在drop或truncate某个分区时不影响该索引的其他分区索引的使用,也就是索引不会失效,维护起来比较方便,但是在查询性能稍微有点影响。
create index idx_ta_c2 on ta(c2) local (partition p1,partition p2,partition p3,partition p4);
或者 create index idx_ta_c2 on ta(c2) local ;
另外在create unique index idx_ta_c2 on ta(c2) local ;系统会报ORA-14039错误,这是因为ta表的分区列是c1,不支持在分区表上创建PK主键或时主键列不包含分区列,创建唯一约束也不可以这样。 oracle
全局索引就是在全表上创建索引,它可以创建自己的分区,可以和分区表的分区不一样,也就是它是独立的索引。
在drop或truncate某个分区时需要创建索引alter index idx_xx rebuild,也可以通过alter table table_name drop partition partition_name update global indexes;实现,但是如果数据量很大则要花很长时间在重建索引上。
可以通过查询user_indexes、user_part_indexes和user_ind_partitions视图来查看索引是否有效。
create index idx_ta_c3 on ta(c3);
或者把全局索引分成多个区(注意和分区表的分区不一样):
create index idx_ta_c4 on ta(c4) global partition by range(c4)(partition ip1 values less than(10000),partition ip2 values less than(20000),partition ip3 values less than(maxvalue));
注意全局索引上的引导列要和range后列一致,否则会有ORA-14038错误。如不能这样写:create index idx_ta_c4 on ta(c1) global partition by range(c4)(partition ip1 values less than(10000),partition ip2 values less than(20000),partition ip3 values less than(maxvalue));
oracle会对主键自动创建全局索引
如果想使某个分区索引置为不可用则可以用如下脚本:
alter index idx_tab1 modify partition "ind partition name" unusable
如果想在主键的列上创建分区索引,除非主键包括分区键,还有就是主键建在两个或以上列上,否则不能创建。
在频繁删除表的分区且数据更新比较频繁时为了维护方便要避免使用全局索引。
导出子分区:exp test1/test1 tables=ta:p1 file=part_1.dmp
分区用到的视图:管理
user_tab_partitions,
user_part_indexes,
user_part_tables,
user_partial_drop_tabs,
user_part_indexes
user_part_key_columns
========================
查询分区表:select * from hcl partition(p_200809)
导出分区表:exp username/pwd file=/aa.dmp tables=(hcl:p_200809,hcl:p_200810)