(一)什么是间隔分区

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

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

(二)创建间隔分区

(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)间隔分区创建限制

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

(2.3)INTERVAL关键字解读

在创建自动间隔分区的时候,最为核心的就是”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;

(2.3.2)NUMTODSINTERVAL(x,c)

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

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

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

(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)

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

Oracle间隔(interval)分区的更多相关文章

  1. Oracle 11g 的bug?: aix 上,expdp 11.2.0.1 导出,impdp 11.2.0.3 导入,Interval 分区的 【Interval】 分区属性成了【N】

    如题: Oracle 11g 的bug?: aix 上,expdp 11.2.0.1 导出,impdp 11.2.0.3 导入,Interval 分区的 [Interval] 分区属性成了[N] 谨记 ...

  2. Oracle数据库表分区

    一.Oracle数据库表分区概念和理解         1.1.已经存在的表没有方法可以直接转化为分区表.         1.2.不在分区字段上建立分区索引,在别的字段上建立索引相当于全局索引.效率 ...

  3. 深入学习Oracle分区表及分区索引

    关于分区表和分区索引(About Partitioned Tables and Indexes)对于10gR2而言,基本上可以分成几类: •       Range(范围)分区 •       Has ...

  4. oracle 分区表和分区索引

    很复杂的样子,自己都没有看完,以备后用 http://hi.baidu.com/jsshm/item/cbfed8491d3863ee1e19bc3e ORACLE分区表.分区索引ORACLE对于分区 ...

  5. ORACLE分区表、分区索引详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt160 ORACLE分区表.分区索引ORACLE对于分区表方式其实就是将表分段 ...

  6. 【三思笔记】 全面学习Oracle分区表及分区索引

    [三思笔记]全面学习Oracle分区表及分区索引 2008-04-15 关于分区表和分区索引(About PartitionedTables and Indexes) 对于 10gR2 而言,基本上可 ...

  7. 简单ORACLE分区表、分区索引

    前一段听说CSDN.COM里面很多好东西,同事建议看看合适自己也可以写一写,呵呵,今天第一次开通博客,随便写点东西,就以第一印象分区表简单写第一个吧. ORACLE对于分区表方式其实就是将表分段存储, ...

  8. Oracle基础 表分区

    Oracle基础 表分区 一.表分区 (一)表分区的分类 1.范围分区(range) 2.散列分区(hash) 3.列表分区(list) 4.复合分区:范围-哈希(range-hash).范围-列表( ...

  9. Oracle 分区表-Range分区

    原文:http://www.tuicool.com/articles/MzeM7r 一.什么是分区表 Oracle提供了分区技术以支持VLDB(Very Large DataBase).分区表通过对分 ...

随机推荐

  1. server computer anaconda

    star@xmatrix:~/Anaconda$ star@xmatrix:~/Anaconda$ conda create -n wind1 python=3.6Solving environmen ...

  2. 【转】Redis哨兵(Sentinel)模式

    主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用.这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式. 一.哨兵 ...

  3. await 只能在 async 中使用吗? 并不是

    for await (let a of [1,2,3]) { console.log(a) } ​

  4. IntelliJ IDEA Error:(24, 35) java: 常量字符串过长

    在转换一个JSON转Java对象是 idea 编译不通过  提示:Error:(24, 35) java: 常量字符串过长 File -> Settings -> Build,Execut ...

  5. [线性代数xOI/ACM]系数矩阵的QGXZ分解

    一些无关紧要的Q&A Q:你是怎么想到这个花里胡哨的算法的啊? A:前几天学习线性代数时有幸和Magolor大佬讨论到 $LU$ 分解在多解时的时间复杂度问题,于是yy出了这个奇怪(?)的算法 ...

  6. 快速安装Python3+RobotFrameowork自动化测试环境

    1. 安装Python3(笔者这里安装的Python3.6.5) 安装 robotframework :   pip install robotframework -U pip install rob ...

  7. [原]部署kubernetes dashboard(二)

    #######################    以下为声明  ##################### 此文档是之前做笔记在两台机上进行的实践,kubernetes处于不断开发阶段 不能保证每 ...

  8. 小程序报错:对应的服务器 TLS 为 TLS 1.0 ,小程序要求的 TLS 版本必须大于等于 1.2

    我这里出现此错误的原因是,搭载域名网站的服务器是windows2008 r2,配置的域名证书是TLS1.0版本,需要在服务器注册表中加入TLS的其他版本. 处理办法如下 小程序报错 TLS 版本必须大 ...

  9. Spring boot启动成功后输出提示

    添加logback-spring.xml,将log输出到文件,控制台输出的level改为error因此只会出处banner src/main/resources/banner.txt的内容为 star ...

  10. jdk7中hashmap实现原理和jdk8中hashmap的改进方法总结

    1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1 ...