oracle 11g新增了间隔分区、虚拟列分区和引用分区。详细的介绍请查看官方文件:
Creating Partitions
1. 间隔分区
间隔分区是范围分区的一种扩展。在引入间隔分区之前,DBA 需要显式定义每个分区的值范围,随着分区值的增长可用分区会逐渐减少直到没有可使用的分区为止。而间隔分区就是为了解决插入表中的数据超过了所有范围分区时而不能自动创建分区的问题。必须至少创建一个范围分区,范围分区的键值确定范围分区的上限值,超过该上限值数据库服务器自动创建特定间隔的分区。
主要用在可预知的添加小范围分区或固定时间类型的分区添加上。
限制条件如下:
1) 只能指定一个分区键列,并且该键列必须是 NUMBER 或 DATE 类型。
2) 索引表不支持间隔分区。
3) 不能为间隔分区创建域索引
4) 不能为分区指定具体名称,由系统自动生成,格式为:SYS_Pnnn,n为数字。
Date类型测试:
创建时间类型间隔分区时指定NUMTOYMINTERVAL(n,day|month|year)子句确定分区扩展的条件,n为数字,指定按n天/月/年的方式进行分区新增。
CREATE TABLE SH.SALES_INTERVAL
PARTITION BY RANGE (time_id)
INTERVAL (NUMTOYMINTERVAL(1,'month')) STORE IN (tbs1,tbs2,tbs3,tbs4)
(
PARTITION P1 values less than (TO_DATE('1-1-2002','dd-mm-yyyy')),
PARTITION P2 values less than (TO_DATE('1-1-2003','dd-mm-yyyy')),
PARTITION P3 values less than (TO_DATE('1-1-2004','dd-mm-yyyy')))
AS
SELECT *
FROM SH.SALES
WHERE TIME_ID < TO_DATE('1-1-2004','dd-mm-yyyy');
select partition_name from user_tab_partitions where table_name='SALES_INTERVAL';
PARTITION_NAME
---------------------------
P1
P2
P3
insert into sh.SALES_INTERVAL values(101001,4,to_date('2005-1-10','yyyy-mm-dd'),10,124,100,200);
insert into sh.SALES_INTERVAL values(101002,5,to_date('2006-1-14','yyyy-mm-dd'),11,125,100,300);
select partition_name from user_tab_partitions where table_name='SALES_INTERVAL';
PARTITION_NAME
---------------------------
P1
P2
P3
SYS_P121
SYS_P122
Number类型测试:
create table sh.test_interval
(
id number,
name varchar2(20)
)
PARTITION BY RANGE (id)
INTERVAL (100)
(PARTITION P001 values less than(500) ,
PARTITION P002 values less than(1000)
);
insert into sh.test_interval select rownum,'A'||rownum from dual connect by level <1201;
select partition_name from user_tab_partitions where table_name='TEST_INTERVAL';
PARTITION_NAME
------------------------------
P001
P002
SYS_P134
SYS_P135
SYS_P136
select count(*) from TEST_INTERVAL PARTITION(SYS_P134);
COUNT(*)
----------
100
select count(*) from TEST_INTERVAL PARTITION(SYS_P135);
COUNT(*)
----------
100
合并分区:
需要注意,分区一定要连续,否则报ORA-14274
alter table SALES_INTERVAL merge partitions for(to_date('2005-10-10','yyyy-mm-dd')),for(to_date('2005-11-10','yyyy-mm-dd')) into partition SYS_P137
强制创建:
LOCK TABLE SALES_INTERVAL PARTITION FOR(to_date('2008-1-14','yyyy-mm-dd')) IN SHARE MODE;
范围分区转换为间隔分区:
alter table TEST drop partition p_max;
alter table TEST set interval(numtodsinterval(1,'DAY'))
alter table TEST set STORE IN (P1,P2,P3,P4)
2. 基于虚拟列的分区
如果某个表的列值是通过计算函数或表达式得到的,则这些列就称为虚拟列。可以在 CREATE 或 ALTER 表操作过程中指定这些列。虚拟列与其它实际表列共享相同的 SQL 名称空间,并与对其进行描述的基础表达式的数据类型相一致。可像其它表列一样在查询 中使用这些列,因此可在 SQL 语句中提供简单、优美且一致的访问表达式机制。
虚拟列的值实际上并未存储在磁盘上的表行中,而是根据需要进行计算。描述虚拟列的函数或表达式应是明确且唯一的,即相同的输入值集应返回相同的输出值。
可以像使用任何其它表列一样使用虚拟列。可对虚拟列进行索引,可在查询、DML 和 DDL 语句中使用它们。可在虚拟列上对表和索引进行分区,甚至可以收集它们的统计信息。 可使用虚拟列分区对表的虚拟列上定义的键列进行分区。对逻辑分区对象的业务要求经常 与现有列不一一对应。随着 Oracle Database 11g 的推出,分区功能得到了增强,可以在虚 拟列上定义分区策略,因而可以更全面地满足业务要求。
如果分区键上的谓词属于以下类型之一,则将对虚拟列分区键执行分区修剪:
• 等式或 Like
• 列表
• 范围
• 扩展分区名称
创建测试表
CREATE TABLE employees
(employee_id number(6) not null, first_name varchar2(30),
last_name varchar2(40) not null, emailvarchar2(25),
phone_number varchar2(20), hire_date date not null,
job_id varchar2(10) not null, salary number(8,2),
commission_pct number(2,2), manager_id number(6),
department_id number(4),
total_compensation as (salary *( 1+commission_pct))
)
PARTITION BY RANGE (total_compensation)
(
PARTITION p1 VALUES LESS THAN (50000),
PARTITION p2 VALUES LESS THAN (100000),
PARTITION p3 VALUES LESS THAN (150000),
PARTITION p4 VALUES LESS THAN (MAXVALUE)
);
插入数据:
insert into employees_inv
(EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
EMAIL,
PHONE_NUMBER,
HIRE_DATE,
JOB_ID,
SALARY,
COMMISSION_PCT,
MANAGER_ID,
DEPARTMENT_ID)
select EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
EMAIL,
PHONE_NUMBER,
HIRE_DATE,
JOB_ID,
SALARY,
COMMISSION_PCT,
MANAGER_ID,
DEPARTMENT_ID
from employees
where COMMISSION_PCT is not null
and rownum < 10;
确认:
select EMPLOYEE_ID,SALARY,COMMISSION_PCT,TOTAL_COMPENSATION from employees_inv;
EMPLOYEE_ID SALARY COMMISSION_PCT TOTAL_COMPENSATION
---------- ---------- -------------- ------------------
14000 .4 19600
13500 .3 17550
12000 .3 15600
11000 .3 14300
10500 .2 12600
10000 .3 13000
9500 .25 11875
9000 .25 11250
8000 .2 9600
3. 引用分区
引用分区通过在create table中指定PARTITION BY REFERENCE子句实现分区,不需要指定分区列,分区信息继承自父表且自动维护。
创建测试表:
CREATE TABLE orders
( order_id NUMBER(12),
order_date date,
order_mode VARCHAR2(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_2005 VALUES LESS THAN (TO_DATE('01-APR-2005','DD-MON-YYYY')),
PARTITION Q2_2005 VALUES LESS THAN (TO_DATE('01-JUL-2005','DD-MON-YYYY')),
PARTITION Q3_2005 VALUES LESS THAN (TO_DATE('01-OCT-2005','DD-MON-YYYY')),
PARTITION Q4_2005 VALUES LESS THAN (TO_DATE('01-JAN-2006','DD-MON-YYYY'))
);
创建测试子表:
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);
确认分区:
select table_name,partition_name from user_tab_partitions where table_name like '%ORDER%' order by 1,2;
TABLE_NAME PARTITION_NAME
------------------------------ ------------------------------
ORDERS Q1_2005
ORDERS Q2_2005
ORDERS Q3_2005
ORDERS Q4_2005
ORDER_ITEMS Q1_2005
ORDER_ITEMS Q2_2005
ORDER_ITEMS Q3_2005
ORDER_ITEMS Q4_2005
父表添加分区
alter table orders add partition Q1_2006 values less than (TO_DATE('01-APR-2006','DD-MON-YYYY'));
Table altered.
SH@PROD3> select table_name,partition_name from user_tab_partitions where table_name like '%ORDER%' order by 1,2;
TABLE_NAME PARTITION_NAME
------------------------------ ------------------------------
ORDERS Q1_2005
ORDERS Q1_2006
ORDERS Q2_2005
ORDERS Q3_2005
ORDERS Q4_2005
ORDER_ITEMS Q1_2005
ORDER_ITEMS Q1_2006
ORDER_ITEMS Q2_2005
ORDER_ITEMS Q3_2005
ORDER_ITEMS Q4_2005
子表添加分区
SH@PROD3> alter table ORDER_ITEMS add partition Q2_2006 values less than (TO_DATE('01-JUL-2006','DD-MON-YYYY'));
alter table ORDER_ITEMS add partition Q2_2006 values less than (TO_DATE('01-JUL-2006','DD-MON-YYYY'))
*
ERROR at line 1:
ORA-14650: operation not supported for reference-partitioned tables
其他说明:
- 如果未显式指定表空间,则引用分区表的分区将与父表的对应分区保存在同一位置。
- 与其它分区表一样,可以指定对象级的默认属性和覆盖对象级默认值的分区描述符。
- 不能禁用引用分区表的外键约束条件。
- 不允许添加或删除引用分区表的分区。但是,在父表上执行分区维护操作将自动级联到子表。