Oracle间隔(interval)分区
(一)什么是间隔分区
间隔分区是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:
- Hang (Process Hang)
- Waits for "library cache lock"
- Waits for "library cache load lock"
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)分区的更多相关文章
- 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] 谨记 ...
- Oracle数据库表分区
一.Oracle数据库表分区概念和理解 1.1.已经存在的表没有方法可以直接转化为分区表. 1.2.不在分区字段上建立分区索引,在别的字段上建立索引相当于全局索引.效率 ...
- 深入学习Oracle分区表及分区索引
关于分区表和分区索引(About Partitioned Tables and Indexes)对于10gR2而言,基本上可以分成几类: • Range(范围)分区 • Has ...
- oracle 分区表和分区索引
很复杂的样子,自己都没有看完,以备后用 http://hi.baidu.com/jsshm/item/cbfed8491d3863ee1e19bc3e ORACLE分区表.分区索引ORACLE对于分区 ...
- ORACLE分区表、分区索引详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt160 ORACLE分区表.分区索引ORACLE对于分区表方式其实就是将表分段 ...
- 【三思笔记】 全面学习Oracle分区表及分区索引
[三思笔记]全面学习Oracle分区表及分区索引 2008-04-15 关于分区表和分区索引(About PartitionedTables and Indexes) 对于 10gR2 而言,基本上可 ...
- 简单ORACLE分区表、分区索引
前一段听说CSDN.COM里面很多好东西,同事建议看看合适自己也可以写一写,呵呵,今天第一次开通博客,随便写点东西,就以第一印象分区表简单写第一个吧. ORACLE对于分区表方式其实就是将表分段存储, ...
- Oracle基础 表分区
Oracle基础 表分区 一.表分区 (一)表分区的分类 1.范围分区(range) 2.散列分区(hash) 3.列表分区(list) 4.复合分区:范围-哈希(range-hash).范围-列表( ...
- Oracle 分区表-Range分区
原文:http://www.tuicool.com/articles/MzeM7r 一.什么是分区表 Oracle提供了分区技术以支持VLDB(Very Large DataBase).分区表通过对分 ...
随机推荐
- CentOS 7 卸载OpenJdk安装Oracle Jdk1.8
CentOS 7 卸载OpenJdk安装Oracle Jdk1.81.查询openjdk:rpm -qa | grep jdk2.卸载OpenJdkrpm -e --nodeps 查询到的结果3.安装 ...
- base64加密后无法解密
记录一个问题: 使用java,或者命令行 base64 命令加密图片文件成加密数据后无法还原成图片 深入:使用java base64工具(sun base64或bouncycastle)加密的数据替换 ...
- 【转】Redis哨兵(Sentinel)模式
主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用.这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式. 一.哨兵 ...
- ubuntu apt-get 安装jdk
参考地址:https://blog.csdn.net/ywueoei/article/details/80335799 . https://blog.csdn.net/inhumming/articl ...
- pipeline配置sonar和自动化
1.sonar配置webhooks, 2.url填写jenkins的地址:http://jenkinsurl/sonarqube-webhook/ 3.前提:jenkins配置好sonar的scann ...
- cmake 指定gcc/g++版本
export CC=/usr/local/bin/gcc export CXX=/usr/local/bin/g++ cmake /path/to/your/project make
- Emiya 家今天的饭
\(dp_{i,j,k}\)表示前\(i\)种烹饪方法,假设最多的是食材\(j\),食材\(j\)比其他食材多\(k\)次出现 其中\(i \in [1,n],j \in [1,m],k \in [- ...
- Linux内核中的双向链表struct list_head
一.双向链表list_head Linux内核驱动开发会经常用到Linux内核中经典的双向链表list_head,以及它的拓展接口和宏定义:list_add.list_add_tail.list_de ...
- GetComponentsInChildren<Transform>(true)
GetComponentsInChildren<Transform>(true);//游戏对象下的子物体激活的没激活的都会被拿到,包括游戏对象本身GetComponentsInChildr ...
- CORS解决跨域问题(403问题)
1.什么是跨域问题? 跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是用当前页同域名同端口的路径,这能有效的阻止跨站攻击. 2.跨域问题出现的条件: 1.跨域问题是a ...