oracle数据库分区表备份

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle数据库分区表备份相关的知识,希望对你有一定的参考价值。

目前有这么一个需求,数据库表使用的是分区表,按月进行分区,现在数据增长量比较大,每天增长一个G左右,硬盘支撑不了,现在需要一个清理方案,清理历史数据,并清理历史表空间,腾出空间。保留一年在线数据,历史数据备份到另外一个空数据库
建表如下,2011会扩充2011对应的分区,格式一样
create table par_tab(
data_date varchar2(8),
col_n varchar2(20)
)
partition by range(data_date)(
partition part_201000 values less than ('201001') tablespace tab_201000,
partition part_201001 values less than ('201002') tablespace tab_201003,
partition part_201002 values less than ('201003') tablespace tab_201003,
partition part_201003 values less than ('201004') tablespace tab_201003,
partition part_201004 values less than ('201005') tablespace tab_201006,
partition part_201005 values less than ('201006') tablespace tab_201006,
partition part_201006 values less than ('201007') tablespace tab_201006,
partition part_201007 values less than ('201008') tablespace tab_201009,
partition part_201008 values less than ('201009') tablespace tab_201009,
partition part_201009 values less than ('201010') tablespace tab_201009,
partition part_201010 values less than ('201011') tablespace tab_201012,
partition part_201011 values less than ('201012') tablespace tab_201012,
partition part_201012 values less than ('201013') tablespace tab_201012,
partition part_201099 values less than ('201099') tablespace tab_201099
);

Oracle提供了分区技术以支持VLDB(Very Large DataBase)。分区表通过对分区列的判断,把分区列不同的记录,放到不同的分区中。分区完全对应用透明。

Oracle的分区表可以包括多个分区,每个分区都是一个独立的段(SEGMENT),可以存放到不同的表空间中。查询时可以通过查询表来访问各个分区中的数据,也可以通过在查询时直接指定分区的方法来进行查询。

分区提供以下优点:

由于将数据分散到各个分区中,减少了数据损坏的可能性;

可以对单独的分区进行备份和恢复;

可以将分区映射到不同的物理磁盘上,来分散IO;

提高可管理性、可用性和性能。

Oracle提供了以下几种分区类型:

范围分区(range);

哈希分区(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的在线重定义表功能:

Oracle的在线重定义表功能(二):

索引也可以进行分区,分区索引有两种类型:global和local。对于local索引,每一个表分区对应一个索引分区,当表的分区发生变化时,索引的维护由Oracle自动进行。对于global索引,可以选择是否分区,而且索引的分区可以不与表分区相对应。当对分区进行维护操作时,通常会导致全局索引的INVALDED,必须在执行完操作后REBUILD。Oracle9i提供了UPDATE GLOBAL INDEXES语句,可以使在进行分区维护的同时重建全局索引。

全局索引可以包含多个分区的值 局部索引比全局索引容易管理,而全局索引比较快
注意:不能为散列分区 或者 子分区创建全局索引

Oracle的分区功能十分强大。不过用起来发现有两点不大方便:

第一是已经存在的表没有方法可以直接转化为分区表。不过Oracle提供了在线重定义表的功能,可以通过这种方式来完成普通表到分区表的转化。可以参考这个例子:

第二点是如果采用了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有如下建议:

■ Tables greater than 2GB should always be considered for partitioning.
■ Tables containing historical data, in which new data is added into the newest partition. A typical example is a historical table where only the current month's data is updatable and the other 11 months are read only.

这些信息是在网上查到的,测试了下确实可以用。
参考技术A 这个简单可以用shell 或bat 调用 export或copy from ,然后用系统定时任务调度一下。27457517追问

目前使用文件copy方式把数据库控制文件、日志文件、数据文件用相同名字的文件系统及目录copy到备份机,使用生产环境取出来的init.ora启动实例并装载数据库,这个比较块
完成后,清理生产环境08 09、10年份的表分区,然后删除对应的表空间,只保留2011数据。清理出空间。但上述完成后还有一个问题,比如2012年备份的时候,这样直接copy2011的数据文件到备份机上是否可以?如果不行,有什么办法解决,备份机要求保留全部历史数据

参考技术B create table par_tab(
data_date varchar2(8),
col_n varchar2(20)
)
partition by range(data_date)(
partition part_201000 values less than ('201001') tablespace tab_201000,
partition part_201001 values less than ('201002') tablespace tab_201003,
partition part_201002 values less than ('201003') tablespace tab_201003,
partition part_201003 values less than ('201004') tablespace tab_201003,
partition part_201004 values less than ('201005') tablespace tab_201006,
partition part_201005 values less than ('201006') tablespace tab_201006,
partition part_201006 values less than ('201007') tablespace tab_201006,
partition part_201007 values less than ('201008') tablespace tab_201009,
partition part_201008 values less than ('201009') tablespace tab_201009,
partition part_201009 values less than ('201010') tablespace tab_201009,
partition part_201010 values less than ('201011') tablespace tab_201012,
partition part_201011 values less than ('201012') tablespace tab_201012,
partition part_201012 values less than ('201013') tablespace tab_201012,
partition part_201099 values less than ('201099') tablespace tab_201099,
partition part_201100 values less than ('201001') tablespace tab_201000,
partition part_201101 values less than ('201002') tablespace tab_201003,
partition part_201102 values less than ('201003') tablespace tab_201003,
partition part_201103 values less than ('201004') tablespace tab_201003,
partition part_201104 values less than ('201005') tablespace tab_201006,
partition part_201105 values less than ('201006') tablespace tab_201006,
partition part_201106 values less than ('201007') tablespace tab_201006,
partition part_201107 values less than ('201008') tablespace tab_201009,
partition part_201108 values less than ('201009') tablespace tab_201009,
partition part_201109 values less than ('201010') tablespace tab_201009,
partition part_201110 values less than ('201011') tablespace tab_201012,
partition part_201111 values less than ('201012') tablespace tab_201012,
partition part_201112 values less than ('201013') tablespace tab_201012,
partition part_201199 values less than ('201099') tablespace tab_201099
);

--- 201101 的时候就这样迁移数据

mkfifo 3.dmp
exp user/pasword rows=y indexes=n TRIGGERS=n DIRECT=y file=3.dmp GRANTS=n log=log/exp_3.log buffer=4096000 tables=par_tab:part_201001 &
imp user/pasword fromuser=user touser=user file=3.dmp ignore=y COMMIT=y buffer=4096000 log=log/imp_3.log
rm 3.dmp

--- 201102 的时候就这样迁移数据
mkfifo 3.dmp
exp user/pasword rows=y indexes=n TRIGGERS=n DIRECT=y file=3.dmp GRANTS=n log=log/exp_3.log buffer=4096000 tables=par_tab:part_201002 &
imp user/pasword fromuser=user touser=user file=3.dmp ignore=y COMMIT=y buffer=4096000 log=log/imp_3.log
rm 3.dmp

依次类推, 迁移完 drop 分区本回答被提问者采纳

Oracle 分区

分区的目的:

  • 改善表的查询性能。

  • 表更容易管理。

  • 备份和恢复操作会执行得更好。

分区表的优点、缺点、特性:

(1)由于将数据分散到各个分区中,减少了数据损坏的可能性;

(2)可以对单独的分区进行备份和恢复;

(3)可以将分区映射到不同的物理磁盘上,来分散IO;

(4)提高可管理性、可用性和性能。

(5)缺点:已经存在的表没有方法可以直接转化为分区表。不过Oracle 提供了在线重定义表的功能。

(6)特殊性:含有LONG、LONGRAW 数据类型的表不能进行分区,一般分区类型为:varchar,varchar2,number,date

(7)每个表的分区或子分区数的总数不能超过1023 个。

什么时候用分区表(设计原则):

(1)单表过大,当表的大小超过2GB,或对于OLTP 系统,表的记录超过1000 万,都应考虑对表进行分区。

(2)历史数据据需要剥离的,表中包含历史数据,新的数据被增加到新的分区中。

(3)查询特征非常明显,比如是按整年、整月或者按某个范围!

(4)基于表的大部分查询应用,只访问表中少量的数据。

(5)按时间段删除成批的数据,例如按月删除历史数据。

(6)按时间周期进行表空间的备份时,将分区与表空间建立对应关系。

(7)如果一个表中大部分数据都是只读数据,通过对表进行分区,可将只读数据存储在只读表空间中,对于大数据库的备份是非常有益的。

(8)对于经常执行并行查询的表应考虑进行分区。

(9)当对表的部分数据可用性要求很高时,应考虑进行表分区。

分区表的类型

1、范围分区(Range Partitioning) 8+,

以某一个范围进行分区。eg:时间段划分。

范围分区特点(如何选择的关键):

(1)最早、最经典、应用最广的分区写法

(2)范围分区通过对分区字段值的范围进行分区

(3)范围分区特别适合于按时间周期进行数据的存储。日、周、月、年等

(4)数据管理能力强(数据迁移、数据备份、数据交换)

(5)范围分区的数据可能不均匀

(6)范围分区与记录值相关,实施难度和可维护性相对较差。

官方案例:

create table sales

(

    prod_id number(6),

    cust_id number,

    time_id date,

    channel_id char(1),

    promo_id number(6),

    quantity_sold number(3),

    amount_sold number(10,2)

)

partition by range(time_id)

(partition soles_al_2006 values less than (to_date('01-APR-2006','dd-mon-yyyy')) tablespace tsa,

partition soles_q2_2006 values less than (to_date('01-JUL-2006','dd-mon-yyyy')) tablespace tsb,

partition soles_q3_2006 values less than (to_date('01-OCT-2006','dd-mon-yyyy')) tablespace tsc,

partition soles_q4_2006 values less than (to_date('01-JAN-2006','dd-mon-yyyy')) tablespace tsd);

2、列表分区(List Partitioning) 9i+

该分区的特点是某列的值只有几个,基于这样的特点我们可以采用列表分区。

列表分区特点(如何选择的关键)

(1)list分区通过对分区字段的离散值进行分区。

(2)list分区是不排序的,而且分区之间没有关联关系

(3)ist分区适合于对数据离散值进行控制

(4)list分区只支持单个字段。

list分区具有与范围分区相似的优缺点:

数据管理能力强

list分区的数据可能不均匀

list分区与记录值相关,实施难度和可维护性相对较差。

官方案例1:

CREATE TABLE sq_soles_by_region

(

   deptno            NUMBER,

   deptname          VARCHAR2 (20),

   quarterly_soles   NUMBER (10, 2),

   state             VARCHAR2 (2)

)

PARTITION BY LIST

   (state)

   (

      PARTITION ql_northwest VALUES ('OR', 'MA'),

      PARTITION ql_southwest VALUES ('AZ', 'UT', 'NM'),

      PARTITION ql_northeast VALUES ('NY', 'VM', 'NJ'),

      PARTITION ql_southeast VALUES ('FL', 'GA'),

      PARTITION ql_northcentral VALUES ('SD', 'WI'),

      PARTITION ql_sourhventrol VALUES ('OK', 'TX'));


官方案例2:


CREATE TABLE sales_by_region

(

   item#        INTEGER,

   qty          INTEGER,

   store_name   VARCHAR (30),

   state_code   VARCHAR (2),

   sale_date    DATE

)

STORAGE (INITIAL 10 K NEXT 20 K)

TABLESPACE tbs5

PARTITION BY LIST (sale_code)

   (PARTITION region_east VALUES

                            ('NA',

                             'NY',

                             'CT',

                             'NH',

                             'ME',

                             'MD',

                             'VA',

                             'PA',

                             'NJ')

       STORAGE (INITIAL 8 K)

       TABLESPACE tbs8,

    PARTITION region_west VALUES

                            ('CA',

                             'AZ',

                             'NM',

                             'OR',

                             'MA')

       NOLOGGING,

    PARTITION REGION_SOUTH VALUES

                             ('TX',

                              'KY',

                              'LA',

                              'MS'),

    PARTITION REGION_NULL VALUES (NULL),

    PARTITION REGION_UNKNOWN VALUES (DEFAULT));

3、哈希分区(Hash Partitioning),8i+,

根据hash 值进行的散列分区,可以有效的消除io 的竞争。更多用在组合分区的子分区中。也称散列分区,这类分区是在列值上使用哈希算法,以确定将行放入哪个分区中,当列的值没有合适的条件时,建议使用哈希分区。

哈希分区也通过指定分区编号来均匀分布数据的一个分区类型,因为通过在I/O设备上进行哈希分区,使得这些分区大小一致。

hash分区的语法看起来比range复杂,其实使用起来比range更简单。

哈希分区的特点(如何选择的关键)

基于分区字段的hash值,自动将记录插入到指定分区

分区数一般是2的幂

易于实施

总体性能最佳

适合于静态数据

hash分区适合于数据的均匀存储

hash分区特别适合于pdml和partition-wise joins。

支持(hash)local indexes

9i不支持(hash)global indexes

10g支持(hash)global indexes hash分区

数据管理能力强

hash分区对数据值无法控制

对于那些无法有效划分范围的表,可以使用hash分区,这样对于提高性能还是会有一定的帮助。hash分区会将表中的数据平均分配到你指定的几个分区中,列所在的分区是依据分区列的hash值自动分配,因此你并不能控制也不知道哪条记录会被放到哪个分区中,hash分区可以支持多个依赖列。

官方案例:

CREATE TABLE scubagear

(

   id     nunber,

   name   VARCHAR2 (60)

)

PARTITION BY HASH (id)

   PARTITIONS 4

      STORE IN (gear1, gear2, gear3, gear4);

    -------------------- ---------------------

  CREATE TABLE dept

(

   deptno     NUMBER,

   deptname   VARCHAR (32)

)

PARTITION BY HASH (deptno)

   PARTITIONS 16;

-----------------------------------------

CREATE TABLE dept

(

   deptno     NUMBER,

   deptname   VARCHAR (32)

)

PARTITION BY HASH

   (deptno)

   (

      PARTITION p1 TABLESPACE ts1,

      PARTITION p2 TABLESPACE ts2,

      PARTITION p3 TABLESPACE ts1,

      PARTITION p4 TABLESPACE ts3);

 --------------------------------------------

4、复合分区,9i 开始,Oracle 就包括了2 种复合分区,RANGE-HASH 和RANGE-LIST。8i+

在11g , Oracle 一下就提供了4 种复合分区: RANGE-RANGE 、LIST-RANGE、LIST-HASH 和LIST-LIST;

复合分区作用

如果某表按照某列分区之后,仍然较大,或者是一些其它的需求,还可以通过分区内再建子分区的方式将分区在分区,即组合分区的方式。

既适合于历史数据,又适合于数据均匀分布

与范围分区一样提供高可用性和管理性

更好的pdml和partition-wise joins性能

实现粒度更细的操作

支持复合 local indexes

不支持复合 composite global indexes

复合分区分类:

RANGE-HASH 

RANGE-LIST 

RANGE-RANGE

--注意顺序,根分区只能是range分区,子分区可以是hash分区,list分区。

LIST-RANGE 

LIST-HASH 

LIST-LIST 

--注意顺序,根分区只能是list分区,子分区可以是hash分区,range分区。

组合分区比range分区更容易管理,充分使用了hash分区的并行优势。

5、间隔分区(Interval Extension to Range Partitioning (11g) ),

它就是以一个区间分区表为“起点”,并在定义中增加了一个规则(即间隔),使数据库知道将来如何增加分区。eg:比如每个月增加一个分区,从而省去了你不断的ADD 或者SPLIT 新的分区。数据库管理员日常要做的一件重复而无聊的工作 比如间隔一天/月要生成新的24个分区,用以存储第二天/月的数据,而在11g中 这项工作可以交给oracle自动完成了,基于range、list、hash的interval partitioning分区类型登场。

官方案例:

CREATE TABLE interval_sales

(

   prod_id         NUMBER (6),

   cust_id         NUMBER,

   time_id         DATE,

   channel_id      CHAR (1),

   promo_id        NUMBER (6),

   quantity_sold   NUMBER (3),

   amount_sold     NUMBER (10, 2)

)

PARTITION BY RANGE

   (time_id)

   INTERVAL ( NUMTOYMINTERVAL (1, 'month') )

   (

      PARTITION p0 VALUES LESS THAN (TO_DATE ('2008-1-1', 'yyyy-mm-dd')),

      PARTITION p1 VALUES LESS THAN (TO_DATE ('2009-1-1', 'yyyy-mm-dd')),

      PARTITION p2 VALUES LESS THAN (TO_DATE ('2010-1-1', 'yyyy-mm-dd')),

      PARTITION p3 VALUES LESS THAN (TO_DATE ('2011-1-1', 'yyyy-mm-dd')));

官方案例2:

CREATE TABLE sales

(

   prod_id         NUMBER (6),

   cust_id         NUMBER,

   time_id         DATE,

   channel_id      CHAR (1),

   promo_id        NUMBER (6),

   quantity_sold   NUMBER (3),

   amount_sold     NUMBER (10, 2)

)

PARTITION BY RANGE

   (time_id)

   INTERVAL ( NUMTOYMINTERVAL (1, 'month') )

   SUBPARTITION BY HASH (cust_id)

      SUBPARTITIONS 4

   (

      PARTITION

         before_2000 VALUES LESS THAN (TO_DATE ('2007-01-01', 'yyyy-mm-dd')))

PARALLEL;

6、参考分区(引用分区)(Referential Partitioning (11g))

对于主子表关系,如果对主表进行了分区,那么可以在子表上根据外键约束来建立对应主表的分区。引用分区可以根据这样一列来创建分区,虽然此列不再被分区的表中,但它是另一个表的外键引用。

这样主表和子表采用相同的等同分区方式,不但连接的时候可以利用partition-wise join ,而且对于主子表的分区操作也会十分方便。而且,这种方式并不需要在子表中存在主表的分区列。

尽量少使用这种,目前虽然oracle推出了,但是基本上用得案例没见着,我这里也不讲了,如果真要用到就查官方手册吧。

官方例子:

CREATE TABLE orders

(

   order_id       NUMBER (12),

   order_date     TIMESTAMP WITH LOCAL TIME ZONE,

   order_mode     VARCHAR (8),

   customer_id    NUMBER (6),

   order_status   NUMBER (2),

   order_total    NUMBER (8, 2),

   sales_rep_id   NUMBER (6),

   promotion_id   NUMBER (6),

   CONSTRAINT orders_pk PRIMARY KEY (order_id)

)

PARTITION BY RANGE

   (order_date)

   (

      PARTITION

         Q1_2017 VALUES LESS THAN (TO_DATE ('2017-01-01', 'yyyy-mm-dd')),

      PARTITION

         Q2_2017 VALUES LESS THAN (TO_DATE ('2017-03-01', 'yyyy-mm-dd')))

CREATE TABLE order_items

(

   order_id       NUMBER (12) NOT NULL,

   line_item_id   NUMBER (3) NOT NULL,

   product_id     NUMBER (6) NOT NULL,

   unit_price     NUMBER (8, 2),

   quantity       NUMBER (8),

   CONSTRAINT order_items_fk FOREIGN KEY

      (order_id)

       REFERENCES orders (order_id)

)

PARTITION BY REFERENCE (order_items_fk);

7、虚拟字段分区(Virtual Column Partitioning (11g)),

虚拟列的值从其他的列推导而来,Oracle 只保存源数据,这个列不占存储空间。虚拟列其中一个引申功能就是虚拟列分区功能。11g 增加对虚拟列的支持,这使得分区功能更加灵活。oracle 11g 新增了虚拟列功能,虚拟列的值从其他的列推导而来,oracle 只保存源数据,这个列并不占用存储空间。

虚拟列其中一个引申功能就是虚拟列分区功能。

在运行时计算,不存储在数据库中,不能更新虚拟列的值。

11g增加对虚拟列的支持,这使得分区功能更加灵活。

定义一个虚拟列的语法;

column_name[datatype] [fenerated always] as [exoression] [vritual]

1>只能在堆组织表(普通表)上创建虚拟列,不能在索引组织表、外部表、临时表上创建虚拟列

2>虚拟列不能是LOB或者RAW

3>虚拟列的值并不是真实存在的、只有用到时,才根据表达式计算出虚拟列的值,磁盘上并不存放。

4>可把虚拟列当做分区关键字建立分区表,这是oracle11g的另一新特性,--虚拟列分区

5>可在虚拟列上建立索引

6>如果在已经创建的表中增加虚拟列时,若没有指定虚拟列的字段类型,oracle 会根据generated always as 后面的表达式计算的结果自动设置该字段的类型

7>虚拟列的值由oracle 根据表达式自动计算得出,不可以做update和insert操作,可以对虚拟列做delete操作,

8>表达式中的所有列必须在同一张表

9>表达式不能使用其他虚拟列

generated always as (

case 

when sales_amt <=10000 then 'LOW'

when sales_amt >10000 and sales_amt<=100000 then 'MEDIUM'

when sales_amt >100000 and sales_amt<=1000000 then 'HIGH'

else 'ULTRA'

end

)


generated always as 

(quantity_sold * amount_sold)


generated always as 

(TO_NUMBER(TO_CHAR(jiondate,'MM')))

8、系统分区11g 

11g以前的分区表,需要指定一个或多个分区字段,并根据这个分区字段的值,按照一定的算法(RANGE,HASH和LIST)来决定一条

记录属于那个分区,从11g开始,oracle允许用户不指定分区列,完全根据程序来控制数据存储在那个分区中。这就是11g提供的系统分区功能

在以前,确定了分区列和分区方式,那么一条数据属于哪个分区也就被确定下来,而对于系统分区而言,分区是分区,数据是数据,二者没用对应的关系。

数据可以被放在任意一个分区中,这不是由数据本身决定的,而是应用程序在插入时确定的。

案例:

create table itpux_s1

(

id NUMBER(20) not null primary key,

name VARCHAR2(20) not null,

age NUMBER(10) not null,

sex VARCHAR2(10) not null,

cardid NUMBER(30) not null,

joindate DATE not null,

region VARCHAR2(12) not null,

tel VARCHAR2(12) not null,

email VARCHAR2(30) not null,

recommend VARCHAR2(10),

identifier VARCHAR2(100)

) tablespace itpux

partition by system

(partition P1,partition P2,partition P3,partition P4);

--插入数据

insert into itpux_s1 partition(P1) select * from itpux_m5 where id <20020000;

insert into itpux_s1 partition(P2) select * from itpux_m5 where id >20019999 and id < 20040000;

--查询验证(简单,详细的参考第3 节视频)

select * from DBA_tab_partitions where table_name='ITPUX_S1';

select * from Dba_Part_Tables where table_name='ITPUX_S1';

select * from dba_tab_subpartitions where table_name='ITPUX_S1';

select count(*) from ITPUX_S1;

select count(*) from ITPUX_S1 partition(P1);


查询验证

user_part_tables   记录分区的表的信息

user_tab_partitions 记录表的分区的信息

user_part_index      查询分区的索引信息

user_tab_subpartitions 子分区查询

dba_part_tables

dba_tab_partitions

dba_part_index

dba_tab_subpartitions

all_part_tables

all_tab_partitions

all_part_index

all_tab_subpartitions


分区索引的作用与分类

与分区表类似(partitioned table),分区索引(partitioned index)也能够提高系统的可管理性,可用性,可伸缩性,及系统性能。

对于索引,需要区分创建的是全局索引,或本地索引:

分区索引既可以与分区表相对独立(全局索引(global index)),

也可以采用与分区表相同的分区方式(本地索引(local index))。

普通表可以建分区索引,分区表可以建非分区的global index,也可以建range 或hash 分区的global index,也可以建基于分区的local index。

使用如下:

表      索引

-----------------

分区    不分区

分区    分区

不分区  分区

不分区  不分区

全局索引(global index):

即可以分区,也可以不分区。即可以建range 分区,也可以建hash 分区,即可建于分区表,又可创建于非分区表上,就是说,全局索引是完全独立的,因此它也需要我们更多的维护操作。

本地索引(local index):

其分区形式与表的分区完全相同,依赖列相同,存储属性也相同。对于本地索引,其索引分区的维护自动进行,就是说你add/drop/split/truncate 表的分区时,本地索引会自动维护其索引分区。

本地索引又可以分为有前缀(prefix)的索引和无前缀(nonprefix)的索引。

而全局索引目前只支持有前缀的索引。

如果本地索引的索引列以分区键开头(分区用什么列分的,索引就用什么列创建,11),则称为前缀局部索引。

如果本地索引的列不是以分区键开头,或者不包含分区键列(分区用什么列分的,索引不用什么列创建。12),则称为非前缀索引。全局索引的索引列必须是以索引分区键作为其前几列。

什么情况下建什么分区索引呢?

1)当有表的分区或子分区操作维护的时候,本地索引提供更好的可用性;

(如合并分区时,只有合并的表分区的分区索引失效,而非分区索引以及全局分区索引在合并.删除表分区后全部失效;可以单独重建本地索引;若只有一个分区需要维护,则只有一个本地索引受影响。

2)本地索引可以提高性能,因为数据大,很多分区必然会被并行的查询。

3)对于历史表,本地索引是必须,这样在有规律的drop 分区的时候,比较方便。

4)本地索引多应用于数据仓库环境中。

5)在非分区字段上建立unique 索引只能建全局索引。

6)全局索引不支持位图索引,全局分区索引全局分区索引只能是B 树索引。

7)全局索引多应用于oltp 系统中。

8)全局分区索引只按范围或者散列hash 分区,hash 分区是10g 以后才支持。

9)表用a 列作分区,索引用b 做局部分区索引,若where 条件中用b 来查询,那么oracle 会扫描所有的表和索引的分区,成本会比分区更高,此时可以考虑用b 做全局分区索引。

本地分区索引是对单个分区的,每个分区索引只指向一个表分区,全局索引则不然,一个分区索引能指向n 个表分区,同时,一个表分区,也可能指向n 个索引分区,对分区表中的某个分区做truncate 或者move,shrink 等,可能会影响到n 个全局索引分区,正因为这点,本地分区索引具有更高的可用性。

1、本地索引 

(1)有前缀的本地索引

create index i_itpux_r1_joindate on itpux_r1(joindate) local;

(2)无前缀的本地索引

create index i_itpux_r1_cardid on itpux_r1(cardid) local;

(3)有前缀的本地分区索引

--drop index i_itpux_r1_joindate

create index i_itpux_r1_joindate on itpux_r1(joindate) local 

(

partition p_i_2014 tablespace ts2014,

partition p_i_2015 tablespace ts2015,

partition p_i_2016 tablespace ts2016,

partition p_i_2017 tablespace ts2017

);

(4)查询 

select dbms_metadata.get_ddl('INDEX','i_itpux_r1_joindate','ITPUX') index_name from dual;

select * from dba_part_indexes where table_name='itpux_r1';

select * from dba_ind_partitions where table_name='itpux_r1';

select * from dba_indexes where table_name='itpux_r1';

select * from dba_ind_columns where table_name='ITPUX_R1';

--查看索引的分配

select segment_name, segment_type, sum(bytes) / 1024 / 1024 from dba_segments where segment_name in (select index_name from dba_indexes where table_name = 'ITPUX_R1') group by segment_name, segment_type;

--查询每个索引分区的分配

select segment_name, segment_type,partition_name, bytes / 1024 / 1024 from dba_segments where segment_name in (select index_name from dba_indexes where table_name = 'ITPUX_R1')

--查看执行计划

select * from itpux_r1 where joindate=to_date('2013-2-28 11:00:00','yyyy-mm-dd hh24:mi:ss');

select * from itpux_r1 where cardid = 10088541614;

2、全局分区索引的创建

前缀、范围、hash

需要手工维护

create index i_itpux_r1_joindate on itpux_r1(joindate) global 

partition by range(joindate)

(

   PARTITION

         sales_q1_2006

         VALUES LESS THAN (TO_DATE ('2014-01-01', 'yyyy-mm-dd')),

      PARTITION

         sales_q2_2006

         VALUES LESS THAN (TO_DATE ('2015-01-01', 'yyyy-mm-dd')),

      PARTITION

         sales_q3_2006

         VALUES LESS THAN (TO_DATE ('2016-01-01', 'yyyy-mm-dd')),

      PARTITION

         sales_q4_2006

         VALUES LESS THAN (maxvalue)

     );


create index i_itpux_r1_joindate on itpux_r1(joindate) global 

partition by hash(joindate)

(

  PARTITION  sales_q1_2006,

      PARTITION   sales_q2_2006,

      PARTITION   sales_q3_2006,

      PARTITION   sales_q4_2006

     );

alter table itpux_r1 drop partition sales_q1_2006;

3、分区索引的重建

--分区索引必须对每个分区重建,不能作为整体重建

alter index i_itpux_r1_joindate rebuild online nologging; --报错:ORA-14086

--删除重建,不在线默认写日志,在线不写日志

select * from dba_ind_partitions where index_owner='ITPUX' and status='UNUSABLE';

select * from dba_ind_partitions where INDEX_name='I_ITPUX_R1_JOINDATE';

--全局索引

--hash 索引分区

alter index i_itpux_r1_joindate rebuild partition P2014 online;

alter index i_itpux_r1_joindate rebuild partition P2015 online;

alter index i_itpux_r1_joindate rebuild partition P2016 online;

alter index i_itpux_r1_joindate rebuild partition P2017 online;

--范围索引分区

alter index i_itpux_r1_joindate rebuild partition P2014 online nologging;

--本地索引

alter index i_itpux_r1_joindate rebuild partition P2014 online nologging;


 

欢迎关注“自学Oracle”



以上是关于oracle数据库分区表备份的主要内容,如果未能解决你的问题,请参考以下文章

100天精通Oracle-实战系列(第24天)Oracle 数据泵表导出导入

100天精通Oracle-实战系列(第24天)Oracle 数据泵表导出导入

100天精通Oracle-实战系列(第24天)Oracle 数据泵表导出导入

oracle recyclebin详解

oracle 分区表

Oracle表分区