Oracle-表分区

使用分区技术的有点:

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;

原文地址:https://www.cnblogs.com/xcnblog3035/p/5256203.html