Oracle提供了分区技术以支持VLDB(Very Large DataBase)。分区表经过对分区列的判断,把分区列不一样的记录,放到不一样的分区中。分区彻底对应用透明。oracle
Oracle的分区表能够包括多个分区,每一个分区都是一个独立的段(SEGMENT),能够存放到不一样的表空间中。查询时能够经过查询表来访问各个分区中的数据,也能够经过在查询时直接指定分区的方法来进行查询。ide
分区提供如下优势: oop
因为将数据分散到各个分区中,减小了数据损坏的可能性; post
能够对单独的分区进行备份和恢复; 性能
能够将分区映射到不一样的物理磁盘上,来分散IO;大数据
提升可管理性、可用性和性能。 ui
Oracle提供了如下几种分区类型:.net
范围分区(range);blog
哈希分区(hash);索引
列表分区(list);
范围-哈希复合分区(range-hash);
范围-列表复合分区(range-list)。
Oracle的普通表没有办法经过修改属性的方式直接转化为分区表,必须经过重建的方式进行转变,下面介绍三种效率比较高的方法,并说明它们各自的特色。
方法一:利用原表重建分区表。
步骤:
SQL> CREATE TABLE T (ID NUMBER PRIMARY KEY, TIME DATE);
表已建立。
SQL> INSERT INTO T SELECT ROWNUM, CREATED FROM DBA_OBJECTS;
已建立6264行。
SQL> COMMIT;
提交完成。
SQL> CREATE TABLE T_NEW (ID, TIME) PARTITION BY RANGE (TIME)
2 (PARTITION P1 VALUES LESS THAN (TO_DATE('2004-7-1', 'YYYY-MM-DD')),
3 PARTITION P2 VALUES LESS THAN (TO_DATE('2005-1-1', 'YYYY-MM-DD')),
4 PARTITION P3 VALUES LESS THAN (TO_DATE('2005-7-1', 'YYYY-MM-DD')),
5 PARTITION P4 VALUES LESS THAN (MAXVALUE))
6 AS SELECT ID, TIME FROM T;
表已建立。
SQL> RENAME T TO T_OLD;
表已重命名。
SQL> RENAME T_NEW TO T;
表已重命名。
SQL> SELECT COUNT(*) FROM T;
COUNT(*)
----------
6264
SQL> SELECT COUNT(*) FROM T PARTITION (P1);
COUNT(*)
----------
0
SQL> SELECT COUNT(*) FROM T PARTITION (P2);
COUNT(*)
----------
6246
SQL> SELECT COUNT(*) FROM T PARTITION (P3);
COUNT(*)
----------
18
优势:方法简单易用,因为采用DDL语句,不会产生UNDO,且只产生少许REDO,效率相对较高,并且建表完成后数据已经在分布到各个分区中了。
不足:对于数据的一致性方面还须要额外的考虑。因为几乎没有办法经过手工锁定T表的方式保证一致性,在执行CREATE TABLE语句和RENAME T_NEW TO T语句直接的修改可能会丢失,若是要保证一致性,须要在执行完语句后对数据进行检查,而这个代价是比较大的。另外在执行两个RENAME语句之间执行的对T的访问会失败。
适用于修改不频繁的表,在闲时进行操做,表的数据量不宜太大。
方法二:使用交换分区的方法。
步骤:
SQL> CREATE TABLE T (ID NUMBER PRIMARY KEY, TIME DATE);
表已建立。
SQL> INSERT INTO T SELECT ROWNUM, CREATED FROM DBA_OBJECTS;
已建立6264行。
SQL> COMMIT;
提交完成。
SQL> CREATE TABLE T_NEW (ID NUMBER PRIMARY KEY, TIME DATE) PARTITION BY RANGE (TIME)
2 (PARTITION P1 VALUES LESS THAN (TO_DATE('2005-7-1', 'YYYY-MM-DD')),
3 PARTITION P2 VALUES LESS THAN (MAXVALUE));
表已建立。
SQL> ALTER TABLE T_NEW EXCHANGE PARTITION P1 WITH TABLE T;
表已更改。
SQL> RENAME T TO T_OLD;
表已重命名。
SQL> RENAME T_NEW TO T;
表已重命名。
SQL> SELECT COUNT(*) FROM T;
COUNT(*)
----------
6264
优势:只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。若是对数据在分区中的分布没有进一步要求的话,实现比较简单。在执行完RENAME操做后,能够检查T_OLD中是否存在数据,若是存在的话,直接将这些数据插入到T中,能够保证对T插入的操做不会丢失。
不足:仍然存在一致性问题,交换分区以后RENAME T_NEW TO T以前,查询、更新和删除会出现错误或访问不到数据。若是要求数据分布到多个分区中,则须要进行分区的SPLIT操做,会增长操做的复杂度,效率也会下降。
适用于包含大数据量的表转到分区表中的一个分区的操做。应尽可能在闲时进行操做。
方法三:Oracle9i以上版本,利用在线重定义功能
步骤:
SQL> CREATE TABLE T (ID NUMBER PRIMARY KEY, TIME DATE);
表已建立。
SQL> INSERT INTO T SELECT ROWNUM, CREATED FROM DBA_OBJECTS;
已建立6264行。
SQL> COMMIT;
提交完成。
SQL> EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'T', DBMS_REDEFINITION.CONS_USE_PK);
PL/SQL 过程已成功完成。
SQL> CREATE TABLE T_NEW (ID NUMBER PRIMARY KEY, TIME DATE) PARTITION BY RANGE (TIME)
2 (PARTITION P1 VALUES LESS THAN (TO_DATE('2004-7-1', 'YYYY-MM-DD')),
3 PARTITION P2 VALUES LESS THAN (TO_DATE('2005-1-1', 'YYYY-MM-DD')),
4 PARTITION P3 VALUES LESS THAN (TO_DATE('2005-7-1', 'YYYY-MM-DD')),
5 PARTITION P4 VALUES LESS THAN (MAXVALUE));
表已建立。
SQL> EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T', 'T_NEW', -
> 'ID ID, TIME TIME', DBMS_REDEFINITION.CONS_USE_PK);
PL/SQL 过程已成功完成。
SQL> EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE('YANGTK', 'T', 'T_NEW');
PL/SQL 过程已成功完成。
SQL> SELECT COUNT(*) FROM T;
COUNT(*)
----------
6264
SQL> SELECT COUNT(*) FROM T PARTITION (P2);
COUNT(*)
----------
6246
SQL> SELECT COUNT(*) FROM T PARTITION (P3);
COUNT(*)
----------
18
优势:保证数据的一致性,在大部分时间内,表T均可以正常进行DML操做。只在切换的瞬间锁表,具备很高的可用性。这种方法具备很强的灵活性,对各类不一样的须要都能知足。并且,能够在切换前进行相应的受权并创建各类约束,能够作到切换完成后再也不须要任何额外的管理操做。
不足:实现上比上面两种略显复杂。
适用于各类状况。
这里只给出了在线重定义表的一个最简单的例子,详细的描述和例子能够参考下面两篇文章。
Oracle的在线重定义表功能:http://blog.itpub.net/post/468/12855
Oracle的在线重定义表功能(二):http://blog.itpub.net/post/468/12962
索引也能够进行分区,分区索引有两种类型:global和local。对于local索引,每个表分区对应一个索引分区,当表的分区发生变化时,索引的维护由Oracle自动进行。对于global索引,能够选择是否分区,并且索引的分区能够不与表分区相对应。当对分区进行维护操做时,一般会致使全局索引的INVALDED,必须在执行完操做后REBUILD。Oracle9i提供了UPDATE GLOBAL INDEXES语句,可使在进行分区维护的同时重建全局索引。
全局索引能够包含多个分区的值 局部索引比全局索引容易管理,而全局索引比较快
注意:不能为散列分区 或者 子分区建立全局索引
Oracle的分区功能十分强大。不过用起来发现有两点不大方便:
第一是已经存在的表没有方法能够直接转化为分区表。不过Oracle提供了在线重定义表的功能,能够经过这种方式来完成普通表到分区表的转化。能够参考这个例子:http://blog.itpub.net/post/468/13091
第二点是若是采用了local分区索引,那么在增长表分区的时候,索引分区的表空间是不可控制的。若是但愿将表和索引的分区分开到不一样的表空间且不一样索引分区也分散到不一样的表空间中,那么只能在增长分区后,对新增的分区索引单独rebuild。
Oracle最大容许存在多少个分区呢?
咱们能够从Oracle的Concepts手册上找到这个信息,对于Oracle9iR2:
Tables can be partitioned into up to 64,000 separate partitions.
对于Oracle10gR2,Oracle加强了分区特性:
Tables can be partitioned into up to 1024K-1 separate partitions.
关于什么时候应该进行分区,Oracle有以下建议: