11g分布表新特性——Interval分区(下)

来源:互联网 发布:jsonp json 区别 编辑:程序博客网 时间:2024/04/29 10:13

Oracle 11g中推出的Interval-Partition特性,是针对Range类型分区的一种功能拓展。对连续数据类型的Range分区,如果插入的新数据值与当前分区均不匹配,Interval-Partition特性可以实现自动的分区创建。

 

目前的Interval-Partition支持的Range分区键类型只有number和date两种类型。在上面的示例中,我们已经演示了数字number类型的分区拓展,下面我们进行date类型演示。

 

1、 Interval-Partition for Date Range

 

笔者认为,相对于number类型的分区拓展,date类型interval-partition分区的应用空间更为广泛。因为实际生产环境下使用某个特定日期范围分区的场景非常多,比如特定年度的交易作为单独分区。

 

同样选择Oracle 11R2的scott用户schema作为实验环境。

 

 

SQL> select * from v$version;

 

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

PL/SQL Release 11.2.0.1.0 - Production

CORE    11.2.0.1.0  Production

 

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 - Production

 

SQL> conn scott/tiger@wilson ;

Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0

Connected as scott

 

SQL> select DEFAULT_TABLESPACE, TEMPORARY_TABLESPACE from dba_users where username='SCOTT';

 

DEFAULT_TABLESPACE             TEMPORARY_TABLESPACE

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

USERS                          TEMP

 

 

我们利用dba_objects数据视图创建分区表,使用last_ddl_time作为分区键。

 

 

SQL> create table t_part

  2  partition by range(last_ddl_time)

  3  interval (numtoyminterval(1,'year'))

  4  (

  5     partition p1 values less than (to_date('2003-1-1','yyyy-mm-dd'))

  6  )

  7  as

  8  select * from dba_objects where 1=0;

 

Table created

 

 

处理中间的interval(numtoyminterval(1,year)),该数据表和其他日期类型分区数据表没有差异。Numtoyminterval表示使用年作为时间间隔,每一年作为一个分区间距。

 

同时,在定义数据表的时候,定义了一个保存2003年之前所有数据的分区p1。此时,我们观察数据字典情况。

 

 

SQL> select segment_name, partition_name,SEGMENT_TYPE, tablespace_name from user_segments where segment_name='T_PART';

 

SEGMENT_NA PARTITION_ SEGMENT_TYPE       TABLESPACE_NAME

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

T_PART     P1         TABLE PARTITION   USERS

 

 

SQL> select table_name, partition_name, high_value, tablespace_name from user_tab_partitions where table_name='T_PART';

 

TABLE_NAME PARTITION_ HIGH_VALUE           TABLESPACE_NAME

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

T_PART     P1         TO_DATE(' 2003-01-01USERS

                       00:00:00', 'SYYYY-M

                      M-DD HH24:MI:SS', 'N

                      LS_CALENDAR=GREGORIA

 

 

分区p1为预定义分区。此时我们向其中插入数据。

 

 

SQL> insert into t_part select * from dba_objects where last_ddl_time<to_date('2003-1-1','yyyy-mm-dd');

3 rows inserted

 

SQL> insert into t_part select * from dba_objects where last_ddl_time>to_date('2003-1-1','yyyy-mm-dd');

72599 rows inserted

 

SQL> commit;

Commit complete

 

 

此时,其中插入的数据已经与原有分区不匹配了。

 

 

SQL> exec dbms_stats.gather_table_stats(user,'T_PART',cascade => true);

 

PL/SQL procedure successfully completed

 

 

 

SQL> select table_name, partition_name, high_value, tablespace_name, num_rows from user_tab_partitions where table_name='T_PART';

 

TABLE_NAME PARTITION_ HIGH_VALUE           TABLESPACE_NAME                  NUM_ROWS

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

T_PART     P1         TO_DATE(' 2003-01-01 USERS                                   3

                       00:00:00', 'SYYYY-M                               

                      M-DD HH24:MI:SS', 'N                                

                      LS_CALENDAR=GREGORIA                               

 

T_PART     SYS_P24    TO_DATE(' 2009-01-01 USERS                                   1

                       00:00:00', 'SYYYY-M                                

                      M-DD HH24:MI:SS', 'N                               

                      LS_CALENDAR=GREGORIA                               

 

T_PART     SYS_P21    TO_DATE(' 2010-01-01 USERS                               71678

                       00:00:00', 'SYYYY-M                               

                      M-DD HH24:MI:SS', 'N                               

                      LS_CALENDAR=GREGORIA                               

 

T_PART     SYS_P22    TO_DATE(' 2011-01-01 USERS                                 711

                       00:00:00', 'SYYYY-M                               

                      M-DD HH24:MI:SS', 'N                               

                      LS_CALENDAR=GREGORIA                                

 

T_PART     SYS_P23    TO_DATE(' 2012-01-01 USERS                                 209

                       00:00:00', 'SYYYY-M                               

                      M-DD HH24:MI:SS', 'N                               

                      LS_CALENDAR=GREGORIA                               

 

 

结论:对于date类型分区键的interval-partition分区表,当不符合分区条件的记录,会自动生成分区进行保存。

 

另外,如果要求对每周的数据划分为分区,可以使用numtodsinterval函数。

 

 

INTERVAL(numtodsinterval(7,'day'))

 

 

2、 Partition Tablespace

 

分区表的创建目的,除了进行分区内局部扫描、便于管理外,还可以通过将分区存放在不同的表空间做到平衡分散IO的目的。所以,对分区的表空间规划,通常是DBA日常决策的一个重要内容。

 

在interval-partition中,分区的创建不是预创建过程,而是系统自动生成。那么,表空间storage如何规划设计呢?

 

从上面的t_part数据分区表中,无论是数据表体,还是各个分区,都没有显示的指明数据分区的表空间存储。从结果看,保存的位置都是users表空间,而users表空间是用户scott的默认表空间。

 

 

SQL> select DEFAULT_TABLESPACE, TEMPORARY_TABLESPACE from dba_users where username='SCOTT';

 

DEFAULT_TABLESPACE             TEMPORARY_TABLESPACE

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

USERS                          TEMP

 

 

说明:如果分区表没有明确表示使用的分区表空间,Oracle会选择用户schema对应的表空间作为分区所在表空间。

 

如果进行部分执行表空间的工作,会如何呢?

 

首先,调整scott用户对应的default tablespace。

 

 

SQL>  select DEFAULT_TABLESPACE, TEMPORARY_TABLESPACE from dba_users where username='SCOTT';

 

DEFAULT_TABLESPACE             TEMPORARY_TABLESPACE

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

SYSTEM                         TEMP

 

 

进行分区表创建。

 

 

SQL> create table t_part

  2  partition by range(sal)

  3  interval (1000)

  4  (

  5     partition p1 values less than (1000),

  6     partition p2 values less than (2000)tablespace SYSAUX

  7  )

  8  as

  9  select * from emp where sal<2000;

 

Table created

 

SQL> select segment_name, partition_name,SEGMENT_TYPE, tablespace_name from user_segments where segment_name='T_PART';

 

SEGMENT_NA PARTITION_ SEGMENT_TYPE       TABLESPACE_NAME

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

T_PART     P1         TABLE PARTITION   SYSTEM

T_PART     P2         TABLE PARTITION   SYSAUX

 

 

在没有使用store in的情况下,我们可以使用tablespace关键字对特殊分区进行指定。如果没有指定,则选择用户默认表空间。

 

 

SQL> insert into t_part select * from emp where sal>=2000;

6 rows inserted

 

SQL> commit;

Commit complete

 

SQL> select segment_name, partition_name,SEGMENT_TYPE, tablespace_name from user_segments where segment_name='T_PART';

 

SEGMENT_NA PARTITION_ SEGMENT_TYPE       TABLESPACE_NAME

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

T_PART     P1         TABLE PARTITION    SYSTEM

T_PART     P2         TABLE PARTITION    SYSAUX

T_PART     SYS_P25    TABLE PARTITION   SYSTEM

T_PART     SYS_P26    TABLE PARTITION   SYSTEM

T_PART     SYS_P27    TABLE PARTITION   SYSTEM

 

 

如果没有明确的指定表空间,Oracle会将创建的分区段保存在所属用户schema对应的默认表空间里。如果需要对预定义分区进行分区指定,需要使用tablespace子句。

 

那么,如果是一个未建立的分区,如何制定创建分区呢?可以使用store in子句。

 

 

SQL> create table t_part

  2  partition by range(sal)

  3  interval (1000) store in (test,PERFSTAT)

  4  (

  5     partition p1 values less than (1000),

  6     partition p2 values less than (2000)

  7  )

  8  as

  9  select * from emp where sal<2000;

 

Table created

 

SQL> select segment_name, partition_name,SEGMENT_TYPE, tablespace_name from user_segments where segment_name='T_PART';

 

SEGMENT_NA PARTITION_ SEGMENT_TYPE       TABLESPACE_NAME

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

T_PART     P1         TABLE PARTITION   SYSTEM

T_PART     P2         TABLE PARTITION   SYSTEM

 

//预定义分区而言,如果不使用tablespace子句,会创建在默认表空间中;

 

SQL> insert into t_part select * from emp where sal>=2000;

6 rows inserted

 

SQL> commit;

Commit complete

 

SQL> select segment_name, partition_name,SEGMENT_TYPE, tablespace_name from user_segments where segment_name='T_PART';

 

SEGMENT_NA PARTITION_ SEGMENT_TYPE       TABLESPACE_NAME

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

T_PART     P1         TABLE PARTITION    SYSTEM

T_PART     P2         TABLE PARTITION    SYSTEM

T_PART     SYS_P28    TABLE PARTITION   TEST

T_PART     SYS_P29    TABLE PARTITION   PERFSTAT

T_PART     SYS_P30    TABLE PARTITION   PERFSTAT

 

 

如果在store in后面标注上tablespaces的列表,那么新创建出的分区就会依次循环的均匀存放在各个分区上。

 

 

SQL> insert into t_part (sal) values(6000);

1 row inserted

 

SQL> commit;

Commit complete

 

SQL> select segment_name, partition_name,SEGMENT_TYPE, tablespace_name from user_segments where segment_name='T_PART';

 

SEGMENT_NA PARTITION_ SEGMENT_TYPE       TABLESPACE_NAME

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

T_PART     P1         TABLE PARTITION    SYSTEM

T_PART     P2         TABLE PARTITION    SYSTEM

T_PART     SYS_P28    TABLE PARTITION    TEST

T_PART     SYS_P29    TABLE PARTITION    PERFSTAT

T_PART     SYS_P30    TABLE PARTITION    PERFSTAT

T_PART     SYS_P31    TABLE PARTITION   TEST

 

6 rows selected

 

 

使用store in子句,可以方便的指定未生成创建分区的表空间分布。

 

3、 结论

 

Oracle 11g中,对于分区表技术提出了很多的新特性,包括新的子分区组织方法、Interval-Partition等等。Interval-Partition技术的推出,笔者认为还是建立在online生产环境的分区自动化管理理念上。在实际生产环境中,进行分区补充或者管理都需要在特定的维护窗口时间和预规划工作。Oracle提供的Interval-Partition,可以帮助DBA实现很多的分区维护工作。