使用分区技术的有点:
1.减少维护工作量,独立管理每个分区比管理单个大表要轻松得多
2.增强数据库的可用性,当一个表的一个或几个分区由于系统故障而不能使用,而其余的分区仍然可以用;如果系统故障只影响表的一部分分区,那么,只有这部分分区需要修复,这就比修复整个大表耗费的时间少许多
3.均衡I/O,减少竞争,通过把表的不同分区分配到不同的磁盘来平衡I/O改善性能
4.分区对用户保持透明,最终用户感觉不到分区的存在
5.提高查询速度:对大表的查询、增加、修改等操作可以分解到表的不同分区中来并行执行,这样就可以加快运行速度,在数据仓库的TP查询特别有用
Oracle 11g相对于其他低版本的Oracle在分区方面增加了很多功能如:
引入扩展的分区功能
Interval分区
外键分区
虚拟列分区
引入了分区建议器
创建分区
A--范围分区
关键字“RANGE”,创建分区后,其中的数据可以根据分区键值指定的范围进行分布,当数据在范围内均匀分时时,性能最好。
如:创建一个商品零售表,然后为该表按照销售日期所在的季度创建4个分区:
create table ware_retail_part(
id integer primary key,
retail_date date,
ware_name varchar2(50))
partition by range(retail_date)
(
--2011年第一季度为part_01分区
partition par_01 values less than(to_date('2011-04-01','yyyy-mm-dd'))tablespace play,
--2011年第二季度为part_02分区
partition par_02 values less than(to_date('2011-07-01','yyyy-mm-dd'))tablespace play,
--2011年第三季度为part_03分区
partition par_03 values less than(to_date('2011-10-01','yyyy-mm-dd'))tablespace users,
--2011年第四季度为part_04分区
partition par_04 values less than(to_date('2012-01-01','yyyy-mm-dd'))tablespace users
)
/
插入若干条记录后
查询数据表ware_retail_part中分区par_02的全部记录
select * from ware_retail_part partition(par_02);
用户通过分区表(分了区的数据表)来查询数据,这种查询速度比从整个表中查询快得多
另外,range分区的字段可以是两个或多个:
如:创建一个商品零售表,然后为该表按照销售编号和销售日期组合创建3个分区:
create table ware_retail_part2
(
id integer primary key,
retail_date date,
ware_name varchar2(50)
)
partition by range(id,retail_date)
(
partition par_01 values less than(10000,to_date('2011-12-01','yyyy-mm-dd'))tablespace play,
partition par_02 values less than(20000,to_date('2012-12-01','yyyy-mm-dd')) tablespace play,
partition par_03 values less than(maxvalue,maxvalue) tablespace users)
/
B--散列分区
HASH分区,在列的取值难以确定的情况下采用的分区方法
对于像身份证号码这种数据散列分区特别有效,其他如范围查询和不等式查询则起不到什么优化作用
如:创建一个商品零售表,然后将该表id列的值根据自身情况散列地存放在指定的两个表空间中:
create table ware_retail_part3(
id integer primary key,
retail_date date,
ware_name varchar2(50)
)
partition by hash(id)
(
partition par_01 tablespace play,
partition par_02 tablespace users
);
然后插入数据
插入的记录到底被分配到哪个分区,用户是无法直接判断的,这是由Oracle系统通过计算id的hash值,然后系统会按照均匀分布的原则自动分配的
所以只能尝试是在partition par_01 还是在partition par_02中
当然,Oracle 11g可以实现自动分配分区名
如:首先创建一个表person,然后为该表创建HASH列(id)分区,要求创建的两个分区由系统自动生成分区名,并分别放置在表空间play,users:
create table person
(
id number primary key,
name varchar2(20),
sex varchar2(2)
)
partition by hash(id)
partitions 2
store in(play,users)
/
另外在,创建HASH分区表时,用户还可以指定所有分区的初始分配空间大小:
如:首先创建一个表Goods,然后为该表创建HASH列分区,要求为创建的表分区指定初始化空间,大小为2048KB
create table goods
(
id number,
goodname varchar2(50)
)
storage(initial 2048k)
partition by hash(id)
(
partition par1 tablespace play,
partition par2 tablespace users
)
/
C--列表分区
关键字是LIST,如果表的某个列的值可以枚举,则可以考虑对表进行列表分区。比如客户表clients那么就可以按照客户所在的省份进行分区
如:首先创建一个用于保存客户信息的表clients,然后以province列为分区键创建列表分区
create table clients
(
id integer primary key,
name varchar2(50),
province varchar2(20)
)
partition by list(province)
(
partition shandong values('山东省'),
partition guangdong values('广东省'),
partition yunnan values('云南省')
)
/
插入数据后,即可按照所有地区查询
D--组合分区
结合两个数据分区的方法可以成为一个组合分区方法。首先用第一个数据分布方法对表格进行分区,然后再用第二个数据分区方法对每个分区进行二次分区
目前的Oracle仅支持对索引组织表(索引和数据一起的表格)进行范围分区,列表分区或散列分区,但不支持对其进行组合分区。
如:首先创建一个保存人员信息的数据表person2,然后创建3个范围分区,每个范围分区又包含2个子分区,子分区没有名字,由系统自动生成,并要求将其分布在2个指定的表空间中:
create table person2
(
id number primary key,
name varchar2(20),
sex varchar2(2)
)
partition by range(id)
subpartition by hash(name)
subpartitions 2 store in(play,users)
(
partition par1 values less than(5000),
partition par2 values less than(10000),
partition par3 values less than(maxvalue)
)
/
该分区首先按照范围进行分区,然后对子分区按照HASH进行分区,根据name列的hash值确定该行分布在paly和users某个表空间上
E--Interval分区
Oracle 11g 新引入的分区方法,是范围分区的一种增强功能,可以实现equi_sized范围分区的自动化。创建的分区作为元数据,只有最开始的分区是永久分区。随着数据的增加会分配更多的部分,并且自动创建新的分区和本地索引
如:首先创建一个表salerecord,然后为该表创建interval分区:
create table salerecord
(
id number primary key,
goodsname varchar2(50),
saledate date,
quantity number
)
partition by range(saledate)
interval(numtoyminterval(1,'year')) --interval分区实现按年份进行自动分区
(
partition par_first values less than(to_date('2012-01-01','yyyy-mm-dd'))
)
/
函数:numtoyminterval()功能是将数字转换成interval year to month
进行interval分区的表格有传统的范围部分和自动生成的interval部分。对于已经进行了范围分区的表格,可以通过alter table ...set interval选项扩展为interval分区的表格
表分区策略
对表进行分区时,首先考虑和分析分区表中每个分区的数据量,其次要为每个分区创建相应的表空间
1.识别大表
一般来说,数据占用存储空间大的表就是大表,系统架构师要做到的就是如何确定哪些表属于大表。如果要在目前运行的系统上进行表数据量分析,那么主要采用analyze table进行分析,然后查询DD获得相应的数据量;如果是一个正在进行需求分析的表,只能采用估计的方法了
2.大表如何分区
大表可以按时间分区。比如,如果按照月份分区,则需要为每个月创建一个数据表空间;如果按照季度分区,则一年要创建4个表空间;如果要创建5年用的表空间,则需要创建20个表空间
3.分区的表空间规划
分区方法确定后,就要着手创建表空间,创建表空间前要对每个表空间的大小进行估算,原则是,往后增长幅度在20%-30%
管理表分区
1.添加表分区
对于已经存在表分区的某个表,如果要添加一个新的表分区,通常使用alter table ...add partition
如:在客户信息表clients中,添加一个省份为“河北省”的表分区:
alter table clients
add partition hebei values('河北省')
storage(initial 10k next 20k) tablespace play
nologging
/
不仅可以增加分区,也可以给增加的分区指定存储属性
2.合并分区
可以减少散列分区或者复合分区的个数。在合并分区之后,Oracle系统将做以下处理:
A-:在合并分区时,HASH列函数将分区的内容分布到一个或多个保留分区中
B-:原来内容所在的分区完全被清除
C-:与分区对应的索引也被清除
D-:将一个或多个索引的本地索引分区标识为不可用(UNSABLE)
E-:需要对不可用的索引进行重建
(1)合并散列分区
如:合并person分区表中的一个HASH分区:
alter table person coalesce partition;
(2)合并复合分区
如:把person2分区表中的part3分区合并到其他保留子分区中:
alter table person2 modify partition par3 coalesce subpartition;
3.删除分区
可以从范围分区或复合分区中删除分区。但是散列分区和复合分区的散列子分区,只能通过合并来达到删除的目的
(1)删除一个表分区
如:把ware_retail_part分区表中的par_04分区删除
alter table ware_retail_part drop partition par_04;
(2)删除有数据和全局索引的表分区
如果分区中包含了数据,并且在表中定义了一个或者多个全局索引,可以使用alter table...drop partition 语句删除表分区,这样可以保留全局索引,但是索引会被标识为不可用(unusable),因而需要重建索引
如:删除ware_retail_part 分区表中的par_04分区,然后重建索引ware_index:
alter table ware_retail_part drop partition par_04;
alter index ware_index rebuild;
(3)使用delete和alter table..drop partition语句
在执行drop partition语句前,要首先执行delete语句来删除分区的所有数据行,然后执行alter table...drop partition,但是执行delete语句时,需要更新全局索引
如:首先删除ware_ratail_part 分区表总第四季度的数据,然后再删除第四季度数据对应的par_04分区
delete from ware_retail_part where retail_date>= to_date('2011-10-01',yyyy-mm-dd);
alter table ware_retail_part drop partition par_04;
(4)删除具有完整性约束的分区
如果分区具有完整性约束,可以采用下面方法:
法一:首先禁止完整性约束,然后执行alter table...drop partition ,最后激活约束
如:首先禁用books_1 表的主键约束 BOOK_PK,然后删除 books_1表的part_01,最后激活books_1表的主键约束BOOK_PK
alter table books_1 disable constraints BOOK_PK;
alter table books_1 drop partition part_01;
alter table books_1 endable constraints BOOK_PK;
法二:
首先执行delete删除分区中的行,然后用alter table..dorp partition
如:首先删除books_1表中part_01分区中的所有记录,然后再删除part_01分区:
delete from books_1 where bookno<1000;
alter table books_1 drop partition part_01;
并入分区
用户使用merge partition将相邻的范围分区合并在一起变为一个新的分区,需要注意,该分区继承原来两个分区的边界;原来的两个分区与相应的索引一起被删除;如果被合并的分区非空,则该分区被标识为unusable;不能对hash分区表执行merge partition语句
并入范围分区是将两个以上的分区合并到一个存在的分区中,合并后一般索引要重建。
如:首先在sales表中创建4个分区,然后再将第3个分区并入到第4个分区中:
create table sales
(
id number primary key,
goodsname varchar2(10),
saledate date
)
partition by range(saledate)
(
partition part_sea1 values less than(to_date('2011-04-01','yyyy-mm-dd')) tablespace play,
partition part_sea2 values less than(to_date('2011-07-01','yyyy-mm-dd')) tablespace users,
partition part_sea3 values less than(to_date('2011-10-01','yyyy-mm-dd'))tablespace play,
partition part_sea4 values less than(to_date('2012-01-01','yyyy-mm-dd')) tablespace users
)
/
在sales表中创建局部索引
create index index_3_4 on sales(saledate)
local(
partition part_sea1 tablespace play,
partition part_sea2 tablespace users,
partition part_sea3 tablespace play,
partition part_sea4 tablespace users
)
/
使用alter table...merge partition 把第3个分区并入到第4个分区中:
alter table sales merge partitons part_sea3,part_sea4 into partition part_sea4;
最后重建局部索引
alter table sales modify partition part_sea4 rebuild unusable local indexes;