现在的位置: 首页 > 数据库 > 正文

Oracle分区详解

2014年11月07日 数据库 ⁄ 共 5001字 暂无评论 ⁄ 阅读 1,151 次
文章目录

分区概念

分区是将一个表或索引物理地分解为多个更小、更可管理的部分。从逻辑上讲分区后仍是只有一个表或一个索引,但在物理上这个表或索引可能由数十个物理分区组成。每个分区都是一个独立的对象,可以独自处理,也可以作为一个更大对象的一部分进行处理。

分区优点

  • 提高数据的可用性:这个特点对任何类型的系统都适用,而不论系统本质上是OLTP还是仓库系统。
  • 减轻了管理的负担:由于从数据库中去除了大段,降低了管理负担。如:在一个100GB的表上执行管理操作时,与在各个10GB的表分区上执行10次同样的操作相比,前者负担要大得多。另外,通过使用分区,可以让净化例程根本不留下空白空间,这就完全消除了重组的必要!
  • 改善某些查询的性能:主要在大型仓库环境中有这个好处,通过使用分区,可以消除很大的数据区间,从而不必考虑它们,相应地根本不用访问这些数据。但这在事务性系统中并不适用,因为这种系统本身就只是访问少量的数据。
  • 减少大容量OLTP系统上的竞争:可以把修改分布到多个单独的分区上,能成比例地减少竞争。

以下将针对每个优点具体讲解:

【提高可用性】

可用性指,当表或索引中一个分区不可用,并不意味着整个对象不用可。

  • 一方面,若查询不涉及非可用分区,则查询仍能正常进行,这样许多用户可能并不会注意到某些数据是不可用的。其原理在于,Oracle 优化器会从查询计划中去除未引用的分区,而未引用分区的不可用状态并不会影响查询结果。
  • 另一方面,分区还可以通过减少停机时间来提高可用性,因为恢复所需的工作量大幅减少。例如,如果有一个100GB的表,它划分为50个2GB的分区。如果某个2GB的分区遭到破坏,现在恢复的时间就只是恢复一个2GB分区所需的时间,而不是恢复一个100GB表的时间,这样就能更快地从错误中恢复。

【减轻管理负担】

与在一个大对象上执行操作相比,在小对象上执行同样的操作从本质上讲更为容易、速度更快,而且占用的资源也更少。

占用资源与速度:

假设数据库中有一个10GB的索引。如果需要重建这个索引,而该索引未分区,你就必须将整个10GB的索引作为一个工作单元来重建,至少需要在某处有10GB的空闲存储空间来存放两个索引的副本,还需要一个临时事务日志表来记录重建索引期间对基表所做的修改。如果将索引本身划分为10个1GB的分区,就可以一个接一个地单独重建各个索引分区。现在只需要原先所需空闲空间的10%。另外,各个索引的重建也更快(可能是原来的10倍),需要向新索引合并的事务修改也更少。

时间风险:

10GB索引的重建即将完成之前,如果出现系统或软件故障会发生什么,我们所做的全部努力都会付诸东流。如果把问题分解,将索引划分为1GB的分区,你最多只会丢掉重建工作的10%。

移植行效率:

若表中有大量“移植行”,此时可能需要重建表进行修正。如果有一个100GB的表,就需要在一个非常大的“块”(chunk)上连续地使用ALTER TABLE MOVE来执行这个操作。而且,如果所在表空间空间不足时重建会失败,这将导致更麻烦的事。然而,如果如果你有25个分区,每个分区的大小为4GB,就可以一个接一个地重建各个分区,甚至可以在单独的会话中并行地执行ALTER TABLE MOVE语句,这就很可能会减少整个操作所需的时间。而且,各分区所占空间较小,遇到表空间空间不足的可能性也较低。你甚至可能发现,移植行都集中在一个很小的分区子集中,因此,可以只重建部分分区,而不是重建整个表。

【改善语句性能】

并行DML

在一个有充足I/O带宽的多CPU主机上,对于大规模的DML操作,若存在分区Oracle会根据对象所有的物理分区数为对象指定一个最大并行度,采用并行DML(parallel DML,PDML)速度的提升可能相当显著。

查询性能:

  • OLTP系统:在OLTP系统中,不应该把分区当作一种大幅改善查询性能的方法。在OLTP系统中,大多数数据获取都通过索引扫描完成。而分区的主要优势在全面扫描时通过分区消除(不考虑某些数据分区)避免大部分扫描,因而分区在性能方面的优势在OLTP中几乎表现不出来。同时,在小索引上分区可能造成读块量增加,运行性能下降。
  • 数据仓库系统:在一个数据仓库/决策支持系统中,分区不仅是一个很强大的管理工具,还可以加快处理的速度。

表分区类型

【区间分区】

这可能是Oracle中最常用的分区机制,可以指定应当存储在一起的数据区间。举例,如:

CREATE TABLE table_name

(column1 date,

column2 varchar2(20)

)

PARTITION BY RANGE (column1)

(PARTITION part_1 VALUES LESS THAN

(to_date('01/01/2005','dd/mm/yyyy')),

PARTITION part_2 VALUES LESS THAN

(to_date('01/01/2006','dd/mm/yyyy')),

PARTITION part_3 VALUES LESS THAN

(MAXVALUE)

);

【散列分区】

指在一个列(或多个列)上应用一个散列函数,行会按这个散列值放在某个分区中。使用散列分区要确保分区键所在列值唯一性大,不能高重复,否则可能造成分区不均匀。如果使用散列分区,你将无从控制一行最终会放在哪个分区中。Oracle会应用散列函数,并根据散列的结果来确定行会放在哪里。如果你由于某种原因希望将某个特定行放在分区PART_1中,就不应该使用散列分区。在散列分区中,分区数应该是2的幂,否则会造成分区分布不均匀。举例,如:

CREATE TABLE table_name

(column1 date,

column2 varchar2(20)

)

PARTITION BY HASH (column1)

(partition part_1 tablespace p1,

partition part_2 tablespace p2

);

【列表分区】

指定一个离散值集,来确定应当存储在一起的数据。例如,可以指定STATUS列值在(’A’,’M’,’Z’)中的行放在分区1中,STATUS值在(‘D’,’P’,’Q’)中的行放在分区2中,依此类推。如下:

create table table_name

(column1 varchar2(20),

column2 varchar2(20)

)

partition by list(column1)

(partition part_1 values ('A','M','Z'),

partition part_2 values ('D','P','Q')

);

如果我们想插入列表分区中未指定的一个值,Oracle会向客户应用返回一个合适的错误。这很类似于一个检查约束,若想改变这个情况可以加一个DEFAULT分区,如:

alter table table_name

add partition

part_3 values ( DEFAULT );

但是,需要注意的是一旦列表分区表有一个DEFAULT分区,就不能再向这个表中增加更多的分区了。若要增加分区,则必须删除DEFAULT分区,然后增加PART_4,再加回DEFAULT分区。

【间隔分区】

间隔分区是Oracle 11g增加的新特性,它与区间分区很类似。间隔分区不需要预先为数据创建分区,而是在插入数据时让数据自己创建分区。要使用间隔分区,首先从一个没有MAXVALUE分区的时间分区表开始,指定一个要增加至上界的间隔(上界是一个最大值,如果达到这个最大值,分区表就要创建一个新的区间)。这个分区表要按某一列进行区间分区,而且这一列应当能增加NUMBER或INTERVAL类型的值(例如,按VARCHAR2字段分区的表就不能进行间隔分区,因为无法让VARCHAR2与某个数字间隔相加)。对任何合适的现有区间表都可以使用间隔分区,也就是说,可以使用ALTER将一个现有的区间表修改为间隔分区,也可以使用CREATE TABLE命令创建一个间隔分区表。

数据库并不是预先创建所有可能的分区,而是随着各个数据行的到来,数据库会查看该月的分区是否存在。如果需要,数据库会创建相应的分区。举例,如:

CREATE TABLE table_name

(column1 date,

column2 varchar2(20)

)

PARTITION BY RANGE (column1)

INTERVAL (numtoyminterval(1,’mouth’))

store in (users,example)

(PARTITION part_1 VALUES LESS THAN

(to_date('01/01/2005','dd/mm/yyyy')),

);

【引用分区】

引用分区是Oracle 11g新增的特性,它处理的是父/子对等分区的问题。也就是说,要以某种方式对子表分区,使得各个子表分区分别与一个父表分区存在一对一的关系。采用引用分区,子表会继承父表的分区机制,而不必对分区键逆规范化。而且,更重要的是,它会让数据库了解子表与父表存在对等分区特点。也就是说,截除或删除相应的子表分区时,也能删除或截除父表分区。

【组合分区】

组合分区是区间分区、散列分区以及列表分区的组合。使用组合分区时,并没有分区段,而只用子分区段。分区本身并没有段(这就是类似于分区表没有段)。数据物理存储在子分区段上,分区成为一个逻辑容器,或者是一个指向实际子分区的容器。

【行移动】

如果用于确定分区的列有修改,且修改会导致行跨分区移动。若表启用了行移动则会移动,否则会报错。

alter table table_name enable row movement;

执行行移动时,实际上在内部就好像行删除了这一行,然后再将其重新插入。不过,尽管在此执行了行的物理删除和插入,在Oracle看来却还是一个更新。因此,不会导致INSERT和DELETE触发器触发,只有UPDATE触发器会触发。

索引分区

对索引进行分区有两种可能的方法:

  • 随表对索引完成相应的分区:这也称为局部分区索引locally pertitioned index)。每个表分区都有一个索引分区,而且只索引该表分区。一个给定索引分区中的所有条目都指向一个表分区,表分区中的所有行都表示在一个索引分区中。
  • 按区间对索引分区:这也称为全局分区索引globally partitioned index)。在此,索引按区间分区(或者在Oracle 10g中该可以按散列分区),一个索引分区可能指向任何(和所有)表分区。

对于全局分区索引,要注意实际上索引分区数可能不同于表分区数。

全局索引只按区间或散列分区,对于列表或组合分区,必须使用局部索引,局部索引会使用底层表相同的机制分区。

【局部索引和全局索引】

数据仓库系统中大多数分区实现使用的都是局部索引;而在OLTP系统中,全局索引则更为常见。这主要取决于是否需要执行“分区消除”来提升性能。

局部索引适用于数据仓库原因:

  • 局部索引可以提高可用性,因为故障会被隔离到一个区间或数据散列上。而对于全局索引,一旦出现故障则所有分区都不可访问。
  • 局部索引维护灵活,当需要移动表分区,只需要将相关的局部索引重建即可。而对于全局索引,所有索引分区都必须实时重建。
  • 在某些情况下,Oracle可以利用索引随表进行局部分区开发最优的查询计划。而对于全局索引,索引和表分区之间就没有这种关系。
  • 局部索引还有利于分区时间点恢复操作,当某个分区需要恢复到比其余表更早的某个时间点时,所有局部分区索引都可以恢复到同样的那个时间点,而所有全局索引则必须在该对象上重建。

【局部索引】

Oracle划分了以下两类局部索引:

  • 局部前缀索引(local prefixed index):在这些索引中,分区键在索引定义的前几列上。例如,一个表在名为LOAD_DATE的列上进行区间分区,该表上的局部前缀索引就是LOAD_DATE作为其索引列列表中的第一列。
  • 局部非前缀索引(local nonprefixed index):这些索引不以分区键作为其列列表的前几列。索引可能包含分区键列,也可能不包含。

【全局索引】

全局索引只有一类,这就是前缀全局索引(prefixed global index)。全局索引的索引键不允许不从该索引的分区键开始。

声明:该笔记转载自《Oracle Database编程艺术:深入数据库体系结构》,仅用于个人学习,若侵犯到您的版权敬请告知!

» 声明:本站文章源于个人经验总结或书籍、互联网转载,内容仅用于个人学习,请勿转载,否则后果自负!

给我留言

留言无头像?