一、为什么要分区(Partition)
1、一般一张表超过2G的大小,ORACLE是推荐使用分区表的。
2、这张表主要是查询,而且可以按分区查询,只会修改当前最新分区的数据,对以前的不怎么做删除和修改。
3、数据量大时查询慢。
4、便于维护,可扩展:11g 中的分区表新特性:Partition(分区)一直是 Oracle 数据库引以为傲的一项技术,正是分区的存在让 Oracle 高效的处理海量数据成为可能,在 Oracle 11g 中,分区技术在易用性和可扩展性上再次得到了增强。
5、与普通表的 sql 一致,不需要因为普通表变分区表而修改我们的代码。
二、oracle 如何按天、周、月、年自动分区
1、按年分区 numtoyminterval(1, ‘year’)
--按年创建分区表
create table test_part
(
ID NUMBER(20) not null,
REMARK VARCHAR2(1000),
create_time DATE
)
PARTITION BY RANGE (CREATE_TIME) INTERVAL (numtoyminterval(1, 'year'))
(partition part_t01 values less than(to_date('2018-11-01', 'yyyy-mm-dd')));
--创建主键
alter table test_part add constraint test_part_pk primary key (ID) using INDEX;
-- Create/Recreate indexes
create index test_part_create_time on TEST_PART (create_time);
2、按月分区 numtoyminterval(1, ‘month’)
--按月创建分区表
create table test_part
(
ID NUMBER(20) not null,
REMARK VARCHAR2(1000),
create_time DATE
)
PARTITION BY RANGE (CREATE_TIME) INTERVAL (numtoyminterval(1, 'month'))
(partition part_t01 values less than(to_date('2018-11-01', 'yyyy-mm-dd')));
--创建主键
alter table test_part add constraint test_part_pk primary key (ID) using INDEX;
3、按天分区 NUMTODSINTERVAL(1, ‘day’)
--按天创建分区表
create table test_part
(
ID NUMBER(20) not null,
REMARK VARCHAR2(1000),
create_time DATE
)
PARTITION BY RANGE (CREATE_TIME) INTERVAL (NUMTODSINTERVAL(1, 'day'))
(partition part_t01 values less than(to_date('2018-11-12', 'yyyy-mm-dd')));
--创建主键
alter table test_part add constraint test_part_pk primary key (ID) using INDEX;
4、按周分区 NUMTODSINTERVAL (7, ‘day’)
--按周创建分区表
create table test_part
(
ID NUMBER(20) not null,
REMARK VARCHAR2(1000),
create_time DATE
)
PARTITION BY RANGE (CREATE_TIME) INTERVAL (NUMTODSINTERVAL (7, 'day'))
(partition part_t01 values less than(to_date('2018-11-12', 'yyyy-mm-dd')));
--创建主键
alter table test_part add constraint test_part_pk primary key (ID) using INDEX;
三、分区表修改
1.1增加一个分区:
分两种情况:(1).没有maxvalue分区。(2).有maxvalue分区。我们创建的分区就是没有maxValue的分区
1.没有maxvalue分区添加新分区:
alter table t_test add partition t_test_2015 VALUESLESS THAN (TO_DATE('2015-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss')) TABLESPACETS_MISPS ;
2、有maxvalue分区添加新分区:
有了maxvalue,就不能直接add partition,而是需要max分区split。例如我们将创建的分区的语句修改下:
alter table t_test split partition t_test_max at(TO_DATE('2016-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss')) into (partitiont_test_2015,partition t_test_max);
2.2 删除一个分区
alter table t_test drop partition t_test_2014
2.3合并分区
相邻的分区可以merge为一个分区,新分区的下边界为原来边界值较低的分区,上边界为原来边界值较高的分区,原先的局部索引相应也会合并,全局索引会失效,需要rebuild。
Alter table t_test merge partitions t_test_2013 ,t_Test_2014 into partition t_Test_2013_to_2014
2.4 使用分区查询:只查询该分区数据
select * from t_testpartition(t_test_2014) where add_date_time >=TO_DATE('2014-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss');
三、给已有的表分区
需要先备份表,然后新建这个表,拷贝数据,删除备份表。
第一种方法:这种方法较慢(不推荐)
-- 1. 重命名
alter table test_part rename to test_part_temp;
-- 2. 创建 partition table
create table test_part
(
ID NUMBER(20) not null,
REMARK VARCHAR2(1000),
create_time DATE
)
PARTITION BY RANGE (CREATE_TIME) INTERVAL (numtoyminterval(1, 'month'))
(partition part_t1 values less than(to_date('2018-11-01', 'yyyy-mm-dd')));
-- 3. 创建主键
alter table test_part add constraint test_part_pk_1 primary key (ID) using INDEX;
-- 4. 将 test_part_temp 表里的数据迁移到 test_part 表中
insert into test_part_temp select * from test_part;
-- 5. 为分区表设置索引
-- Create/Recreate indexes
create index test_part_create_time_1 on TEST_PART (create_time);
-- 6. 删除老的 test_part_temp 表
drop table test_part_temp purge;
-- 7. 作用是:允许分区表的分区键是可更新。
-- 当某一行更新时,如果更新的是分区列,并且更新后的列植不属于原来的这个分区,
-- 如果开启了这个选项,就会把这行从这个分区中 delete 掉,并加到更新后所属的分区,此时就会发生 rowid 的改变。
-- 相当于一个隐式的 delete + insert ,但是不会触发 insert/delete 触发器。
alter table test_part enable row movement;
第二种方法:这种方法较快ji (当然也可以利用时间分区)
create table test_part_temp
PARTITION BY list (lb)
(
partition p01 values ('01'),
partition p02 values ('02'),
partition p03 values ('03'),
partition p04 values ('04'),
partition p05 values ('05'),
partition p06 values ('06'),
partition p07 values ('07'),
partition p08 values ('08'),
partition p09 values ('09'),
partition p10 values ('10'),
partition p11 values ('11')
)
as select t.* from test_part T where t.isdeleted='0'
创建索引如上