Oracle间隔(interval)分区

(一)什么是间隔分区html

间隔分区是Oracle 11.1引入的新功能,经过该功能,能够在输入相应分区的数据时自动建立相应的分区。在没有间隔分区技术以前,DBA一般会建立一个maxvalue分区以免ORA-14400:插入的分区键值不能映射到任何分区("inserted partition key does not map to any partition") 错误。数据库

做为范围分区(range partition)的扩展,间隔分区命令数据库在插入表中的数据超过全部现有范围分区时自动建立指定间隔的分区。DBA必须至少指定一个范围分区的较高值,称为过渡点,数据库会自动的为超出该过渡点的数据建立间隔分区,每一个间隔分区的下边界是先前范围或间隔分区的上边界。express

 

(二)建立间隔分区oracle

(2.1)间隔分区建立语法运维

CREATE TABLE table_name
(
  ...
)
PARTITION BY RANGE(column1)
INTERVAL expr [STORE IN (tablespace1,[tablespace2,...])]
(
  PARTITION partition_name1 VALUES LESS THAN(literal | MAXVALUE) [TABLESPACE tablespace1],
  PARTITION partition_name2 VALUES LESS THAN(literal | MAXVALUE) [TABLESPACE tablespace2]
);

--PARTITION BY RANGE(column1):指定一个分区范围列函数

--INTERVAL:指定分区间隔学习

--STORE IN:指定分区存储的表空间测试

 

(2.2)间隔分区建立限制ui

间隔分区是范围分区的扩展,其支持范围有限,在Oracle 11g中,间隔分区只能指定一个分区键列,而且数据类型必须为NUMBER或者DATE类型。由于TIMESTAMP数据类型是DATE类型的扩展,可在分区键中使用。总结来讲,间隔分区只支持NUMBER和TIME类型。this

 

(2.3)INTERVAL关键字解读

image

在建立自动间隔分区的时候,最为核心的就是”INTERVAL“关键字了。对于按照时间进行自动分区,INTERVAL后面能够跟随NUMTOYMINTERVAL和NUMTODSINTERVAL。两个关键字用法以下:

(2.3.1)NUMTOYMINTERVAL(x,c)

用法:x是一个数据,c是一个字符串,该函数是将x转为interval year to month类型。经常使用单位有:”year“、”month“。

例子:当前时间加3年,当前时间加3个月

SELECT   SYSDATE,
         SYSDATE + NUMTOYMINTERVAL(3,'year')  AS "3年后" ,
         SYSDATE + NUMTOYMINTERVAL(3,'month') AS "3个月后"
  FROM   dual;

image

 

(2.3.2)NUMTODSINTERVAL(x,c)

用法:x是一个数据,c是一个字符串,该函数是将x转为interval day to second类型。经常使用单位有:”day“、”hour“、”minute“、”second“。

例子:当前时间加1天、1小时、1分钟、1秒钟。

image

 

(三)按时间(年、月、日、周)建立间隔分区

(3.1)按”年“自动建立分区(关键字:NUMTOYMINTERVAL)

例子:建立按年自动分区表,按照员工生日(birthday字段),每一年一个分区。

--建立按年分区表

CREATE TABLE interval_year_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTOYMINTERVAL(1,'year')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition2014 VALUES LESS THAN(to_date('2015-01-01:00:00:00','yyyy-mm-dd hh24:mi:ss')),
  PARTITION partition2015 VALUES LESS THAN(to_date('2016-01-01:00:00:00','yyyy-mm-dd hh24:mi:ss'))
);

 

(3.2)按”月“自动建立分区(关键字:NUMTOYMINTERVAL)

例子:建立按月自动分区表,按照员工生日(birthday字段),每个月一个分区。

-- 建立按月分区表

CREATE TABLE interval_month_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTOYMINTERVAL(1,'month')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition201401 VALUES LESS THAN(to_date('2014-02-01:00:00:00','yyyy-mm-dd hh24:mi:ss'))
);

 

(3.3)按”天(日)“自动建立分区(关键字:NUMTODSINTERVAL)

例子:建立按天自动分区表,按照员工生日(birthday字段),天天一个分区。

-- 按天(日)建立分区
CREATE TABLE interval_day_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTODSINTERVAL(1,'day')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition20140101 VALUES LESS THAN(to_date('2014-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss'))
);

 

(3.4)按”周“自动建立分区(关键字:NUMTODSINTERVAL)

例子:建立按周自动分区表,按照员工生日(birthday字段),每周一个分区。须要注意的是,这里使用的关键字与“天”分区同样,都是“day”,只是改成了7天。

-- 按周建立分区

CREATE TABLE interval_week_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTODSINTERVAL(7,'day')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition201401w VALUES LESS THAN(to_date('2014-01-07 00:00:00','yyyy-mm-dd hh24:mi:ss'))
);

 

(3.4)按”小时“自动建立分区(关键字:NUMTODSINTERVAL)

-- 按”小时”进行分区
CREATE TABLE interval_hour_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTODSINTERVAL(1,'hour')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition20140100 VALUES LESS THAN(to_date('2014-01-01 01:00:00','yyyy-mm-dd hh24:mi:ss'))
);

除此以外,还能够按”分钟“、”秒“进行自动分区。

 

(四)按数字(number)建立间隔分区

例子:按数字进行分区相对简单,这里相近的10个数字进入同一个分区

CREATE TABLE interval_number_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(employee_id)
INTERVAL (10) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition10 VALUES LESS THAN(10)
);

 

(五)关于间隔分区的常见问题

(5.1)如何将现有普通表转换为间隔分区

可使用以下命令将现有的范围分区表转换为间隔分区表,注意,仅仅支持范围分区表:

ALTER TABLE <table_name> SET INTERVAL <number or interval expression>;

 

(5.2)如何为现有表设置新的间隔

可使用以下命令修改间隔,该操做不会使index不可用:

ALTER TABLE <table_name> SET INTERVAL(interval express);

例子见MOS文档(1479115.1)。

 

(5.3)如何为间隔分区指定/更改表空间

INTERVAL子句的STORE IN用于指定建立间隔分区的表空间。若是指定了表空间列表,将以循环方式在这些表空间上建立间隔分区。

INTERVAL expr [STORE IN (tablespace1,[tablespace2,...])]

须要注意的是,在INTERVAL子句中使用”PARTITION“建立的范围分区须要指出表空间,不然会将范围分区建立到用户默认的表空间中,而不是[STORE IN]的表空间中。

 

对于已经建立的分区,可使用如下命令将其移动到特定的表空间:

--移动分区到特定表空间
ALTER TABLE <table_name> MOVE PARTITION <partition_name> TABLESPACE <tablespace_name>;

--注:移动分区会致使全局索引失效,需谨慎

 

(5.4)自动建立的间隔分区的名称是什么

数据库建立的间隔分区的名称是系统自动生成的,能够经过dba_tab_partition视图查看。目前没法为分区指定建立模板,可是能够重命名分区。

例子:自动建立的表空间的名称

insert into INTERVAL_NUMBER_TABLE01 values (201209, 'name09');
insert into INTERVAL_NUMBER_TABLE01 values (201210, 'name10');
insert into INTERVAL_NUMBER_TABLE01 values (201211, 'name11');
insert into INTERVAL_NUMBER_TABLE01 values (201212, 'name12');
insert into INTERVAL_NUMBER_TABLE01 values (201301, 'name01');
insert into INTERVAL_NUMBER_TABLE01 values (201402, 'name02');
insert into INTERVAL_NUMBER_TABLE01 values (201503, 'name03');

SQL> select  table_owner,table_name,partition_name,high_value,tablespace_name,interval
  2  from    dba_tab_partitions
  3  where   table_name = 'INTERVAL_NUMBER_TABLE01';

TABLE_OWNER    TABLE_NAME                     PARTITION_NAME     HIGH_VALUE    TABLESPACE_NAME   INTERVAL
-------------- ------------------------------ -----------------  ------------ ----------------- --------
LIJIAMAN       INTERVAL_NUMBER_TABLE01        PARTITION10        10            USERS             NO
LIJIAMAN       INTERVAL_NUMBER_TABLE01        SYS_P54            20            TBS02             YES
LIJIAMAN       INTERVAL_NUMBER_TABLE01        SYS_P55            110           TBS02             YES
LIJIAMAN       INTERVAL_NUMBER_TABLE01        SYS_P56            120           TBS03             YES
LIJIAMAN       INTERVAL_NUMBER_TABLE01        SYS_P57            130           TBS01             YES


--备注:INTERVAL = 'YES'表明自动建立的分区

 

(5.5)使用DBMS_METADATA.GET_DDL检索表时,为何缺乏系统生成的间隔分区?

"DBMS_METADATA.GET_DDL"只提供用户手段建立的分区,而不提供系统自动生成的分区。如下为测试例子:

SQL> SELECT DBMS_METADATA.GET_DDL('TABLE','INTERVAL_NUMBER_TABLE01','LIJIAMAN') FROM DUAL;

DBMS_METADATA.GET_DDL('TABLE',
--------------------------------------------------------------------------------
  CREATE TABLE "LIJIAMAN"."INTERVAL_NUMBER_TABLE01" 
   (  "EMPLOYEE_ID" NUMBER, 
      "EMPLOYEE_NAME" VARCHAR2(20), 
      "BIRTHDAY" DATE
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
  STORAGE(
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" 
  PARTITION BY RANGE ("EMPLOYEE_ID") INTERVAL (10) STORE IN ("TBS01", "TBS02", "TBS03") 
 (PARTITION "PARTITION10"  VALUES LESS THAN (10) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
  NOCOMPRESS LOGGING 
  STORAGE(INITIAL 8388608 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" )

若是要输出系统自动建立的分区的脚本,需将DBMS_METDATA的EXPORT参数设置为true

exec dbms_metadata.set_transform_param(dbms_metadata.SESSION_TRANSFORM,'EXPORT',true);

 

(六)关于间隔分区的bug

之前在使用分区表时,遇到过由延迟段建立(deferred_segment_creation)引发的段分配异常问题。间隔分区也有相似的bug,使用须要谨慎。


Bug 16042673 - Database hang when system trying to add interval partition to the table (Doc ID 16042673.8)

Symptoms:
Related To:
Description
This bug is only relevant when using Partitioned Tables
Concurrent   insert   statements   issued   against  an   interval 
partitioned  table resulting  in the  creation of a new partition 
blocks remaining inserts into the same table.
 
Rediscovery Notes
 If  concurrent  insert  statements  are issued  against  an  interval 
 partitioned  table  and the  insert  statement which  results  in the 
 creation of  a new partition  blocks all  the other  inserts into the 
 table, then we might be encountering this bug.

 

(七)间隔分区的利弊思考

好处:间隔分区经过系统自动建立分区,减小了DBA的平常运维工做,避免了ORA-14400这类错误,每一年年终不须要为下一年手动建立分区,想一想仍是挺开心的;

坏处:由于系统自动建立分区名称,咱们没法经过分区名称来判断数据的存放位置,增长了后期的维护难度。举个例子,若是是DBA手动维护,假设表的分区”part_201901“存储的就是2019年1月的数据,假如咱们想要删除1月份的数据,直接删除该分区便可,若是数据库里面有500个相似的表,直接写批量脚本”ALTER TABLE <table_name> DROP PARTITION part_201901“就将所有表的1月份的数据删除了,可是对于系统自动建立的分区,在不一样的表里面,2019年1月的数据对应的分区名不一样,天然没法使用脚本批量删除,即便有脚本,也很是麻烦。

 

 

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

我的分区(partition)技术相关文档:

1. [oracle]分区表学习    
2. [Oracle]分区索引     
3. Oracle分区表删除分区引起错误ORA-01502: 索引或这类索引的分区处于不可用状态    
4. Oracle split分区表引发ORA-01502错误
5. Oracle在线重定义(online redefinition)--将普通表改成分区表

参考文档:

1. Interval Partitioning Essentials - Common Questions - Top Issues (Doc ID 1479115.1)
2. How to Build an INTERVAL PARTIONED Table using a NUMBER datatype for the INTERVAL Partition. (Doc ID 1514047.1)
3. Bug 16042673 - Database hang when system trying to add interval partition to the table (Doc ID 16042673.8)

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

相关文章
相关标签/搜索