Oracle提供了分区技术以支持VLDB(Very Large DataBase)。分区表通过对分区列的判断,把分区列不同的记录,放到不同的分区中。分区完全对应用透明。
Oracle的分区表可以包括多个分区,每个分区都是一个独立的段(SEGMENT),可以存放到不同的表空间中。查询时可以通过查询表来访问各个分区中的数据,也可以通过在查询时直接指定分区的方法来进行查询。
分区的优点:
(1)由于将数据分散到各个分区中,减少了数据损坏的可能性;
(2)可以对单独的分区进行备份和恢复;
(3)可以将分区映射到不同的物理磁盘上,来分散IO;
(4)提高可管理性、可用性和性能。
分区表和分区索引(About Partitioned Tables and Indexes)的种类
Range分区: Range分区是应用范围比较广的表分区方式,它是以列的值的范围来做为分区的划分条件,将记录存放到列值所在的range分区中。
INTERVAL分区是Oracle11g新增的特性,它是针对Range类型分区的一种功能拓展。对连续数据类型的Range分区,如果插入的新数据值与当前分区均不匹配,Interval-Partition特性可以实现自动的分区创建。
Hash分区:
对于那些无法有效划分范围的表,可以使用hash分区,这样对于提高性能还是会有一定的帮助。hash分区会将表中的数据平均分配到你指定的几个分区中,列所在分区是依据分区列的hash值自动分配,因此你并不能控制也不知道哪条记录会被放到哪个分区中,hash分区也可以支持多个依赖列。
List分区:
List分区也需要指定列的值,其分区值必须明确指定,该分区列只能有一个,不能像range或者hash分区那样同时指定多个列做为分区依赖列,但它的单个分区对应值可以是多个。在分区时必须确定分区列可能存在的值,一旦插入的列值不在分区范围内,则插入/更新就会失败,因此通常建议使用list分区时,要创建一个default分区存储那些不在指定范围内的记录,类似range分区中的maxvalue分区。
组合分区:
如果某表按照某列分区之后,仍然较大,或者是一些其它的需求,还可以通过分区内再建子分区的方式将分区再分区,即组合分区的方式。组合分区呢在10g中有两种:range-hash,range-list。注意顺序,根分区只能是range分区,子分区可以是hash分区或list分区。
Range示例:
创建range分区表:
create table range_tab (id varchar(100),my_date date)
partition by range(my_date)
(
partition p1 values less than(to_date('2015-10-1', 'yyyy-mm-dd')) tablespace test,
partition p2 values less than(to_date('2015-11-1', 'yyyy-mm-dd')) tablespace test,
partition p3 values less than(to_date('2015-12-1', 'yyyy-mm-dd')) tablespace test,
partition p4 values less than(maxvalue)
)
select * from user_part_tables;
select * from user_tab_partitions;
添加range分区
1、原分区里边界是maxvalue或者default。这种情况下,需要把边界分区drop掉,加上新分区后,在添加上新的分区。 或者采用split,对边界分区进行拆分。
alter table range_tab add partition p5 values less than(to_date('2016-01-01', 'yyyy-mm-dd')) tablespace test ;
ERROR at line 1:
ORA-14074: partition bound must collate higher than that of the last partition
alter table range_tab split partition p4 at(to_date('2016-02-01', 'yyyy-mm-dd'))
into (partition p5 tablespace fog,partition p4 tablespace fog)
2、原分区里边界没有maxvalue或者default。直接添加分区即可
alter table range_tab add partition p5 values less than(to_date('2016-01-01', 'yyyy-mm-dd')) tablespace test ;
删除range分区
alter table range_tab drop partition p5;
将range分区替换成interval类型的range分区
原分区里边界是maxvalue或者default。需要删除该分区。
alter table range_tab set interval(numtoyminterval(1,'month'));
将interval分区设置成手动分区
alter table range_tab set interval();
添加range分区索引
global类型的,维护教麻烦,建议使用local类型的
create index range_tab_id_index1 on range_tab(my_date)
global partition by range(my_date)(
partition p1 values less than(to_date('2015-10-1', 'yyyy-mm-dd')) tablespace test,
partition p2 values less than(to_date('2015-11-1', 'yyyy-mm-dd')) tablespace test,
partition p3 values less than(to_date('2015-12-1', 'yyyy-mm-dd')) tablespace test,
partition p4 values less than(to_date('2016-01-1', 'yyyy-mm-dd')) tablespace test,
partition p5 values less than(maxvalue) tablespace test
)
create index range_tab_id_index1 on range_tab(id,my_date) local;
local索引也可以知道分区名和对应的表空间名,但是要注意分区个数必须与表的分区个数想一致
create index range_tab_id_index on range_tab(id,my_date) local
(
partition p1 tablespace test,
partition p2 tablespace test,
partition p3 tablespace test,
partition p4 tablespace test,
partition p5 tablespace test,
partition p6 tablespace test,
partition p7 tablespace test,
partition p8 tablespace test
)
有关分区索引视图
select * from user_part_indexes;
select * from user_ind_partitions;
hash分区
创建hash分区
create table hash_tab (id varchar(20),hash_value varchar2(50))
partition by hash(id)(
partition p1 tablespace test,
partition p2 tablespace test,
partition p3 tablespace test);
需要注意的是hash分区不存在split和drop操作,只能add分区,数据在各个分区的分布情况并不由我们控制,而是通过oracle中的hash函数来操作的,所以我们不能显示的指定某一个分区进行分裂。
alter table hash_tab add partition p4 tablespace test;
创建global类型的hash索引
create index hash_tab_id_index on hash_tab(id)
global partition by hash(id)(
partition p1 tablespace test,
partition p2 tablespace test,
partition p3 tablespace test
)
创建local类型的hash索引
create index hash_tab_id_index on hash_tab(id) local;
list分区
创建list分区表
create table list_tab(id varchar2(20),list_data varchar2(50))
partition by list(id)(
partition p1 values('001'),
partition p2 values('002'),
partition p3 values('003'),
partition p4 values(default)
)
alter table list_tab split partition p4 values ('004')
into (partition p5 tablespace test,partition p4 tablespace test);
删除一个list分区
alter table list_tab drop partition p5;
添加一个list分区(分区里边界不能有maxvalue或者default)
alter table list_tab add partition p5 values('008');
组合分区: 如果某表按照某列分区之后,仍然较大,或者是一些其它的需求,还可以通过分区内再建子分区的方式将分区再分区,即组合分区的方式。
组合分区主要有两种:range-hash,range-list。
range-hash
create table range_hash_tab
(
id varchar2(20),
t_date date
)
partition by range(t_date) subpartition by hash(id)
subpartition template
(
subpartition sub_p1 tablespace test,
subpartition sub_p2 tablespace test,
subpartition sub_p3 tablespace test
)
(
partition p01 values less than(to_date('2015-01-01','yyyy-mm-dd')),
partition p02 values less than(to_date('2016-01-01','yyyy-mm-dd')),
partition p03 values less than(maxvalue)
);
或者
create table range_hash_tab
(
id varchar2(20),
t_date date
)
partition by range(t_date) subpartition by hash(id)
subpartition template
(
subpartition sub_p1 tablespace test,
subpartition sub_p2 tablespace test,
subpartition sub_p3 tablespace test
)
(
partition p01 values less than(to_date('2015-01-01','yyyy-mm-dd')),
partition p02 values less than(to_date('2016-01-01','yyyy-mm-dd')),
partition p03 values less than(maxvalue)
);
range-list
create table range_list_tab
(
id varchar2(20),
t_date date
)
partition by range(t_date) subpartition by list(id)
(partition p01 values less than(to_date('2015-01-01','yyyy-mm-dd'))
(
subpartition p01_sub01 values('001','002'),
subpartition p01_sub02 values('003','004'),
subpartition p01_sub03 values('005','006'),
subpartition p01_sub04 values(default)
),
partition p02 values less than(to_date('2015-02-01','yyyy-mm-dd'))
(
subpartition p02_sub01 values('001','002'),
subpartition p02_sub02 values('003','004'),
subpartition p02_sub03 values('005','006'),
subpartition p02_sub04 values(default)
),
partition p03 values less than(to_date('2015-03-01','yyyy-mm-dd'))
(
subpartition p03_sub01 values('001','002'),
subpartition p03_sub02 values('003','004'),
subpartition p03_sub03 values('005','006'),
subpartition p03_sub04 values(default)
));