Oracle 11g 中的分区表

1、 11g 中的分区表新特性

Partition(分区)一直是 Oracle 数据库引以为傲的一项技术,正是分区的存 在让 Oracle 高效的处理海量数据成为可能,在 Oracle 11g 中,分区技术在易用性 和可扩展性上再次得到了增强。


1.1 Interval Partitioning

在曾经的一个项目中,由于数据量的巨大,所以表设计为每一个小时一个分 区,数据库管理员日常要做的一件重复而无聊的工作就是每隔一天要生成新的 24 个分区,用以存储第二天的数据。而在 11g 中这项工作可以交由 Oracle 自动 完成了,基于 Range 和 List 的 Interval Partitioning 分区类型登场。

CREATE TABLE TB_INTERVAL

PARTITION BY RANGE (time_col)

INTERVAL(NUMTOYMINTERVAL(1, 'month'))

(PARTITION P0 VALUES LESS THAN (TO_DATE('1-1-2010', 'dd-mm-yyyy')));

指定需要 Oracle 自动创建分区的间隔时间,上面这个例子是 1 个月,然后 至少创建一个基本分区,上面这个例子是在 2010-1-1 之前的所有数据都在 P0 分 区中,以后每个月的数据都会存放在 Oracle 自动创建的一个新分区中。


1.2 System Partitioning

系统分区,在这个新的类型中,我们不需要指定任何分区键,数据会进入哪 个分区完全由应用程序决定,实际上也就是由 SQL 来决定,终于,我们在 Insert 语句中可以指定插入哪个分区了。

假设我们创建了下面这张分区表,注意,没有指定任何分区键:


CREATE TABLE systab (c1 integer, c2 integer) PARTITION BY SYSTEM

(

PARTITION p1 TABLESPACE tbs_1,

PARTITION p2 TABLESPACE tbs_2,

PARTITION p3 TABLESPACE tbs_3,

PARTITION p4 TABLESPACE tbs_4 );

现在由 SQL 语句来指定插入哪个分区: 

-- 数据插入 p1 分区

INSERT INTO systab PARTITION (p1) VALUES (4,5);

-- 数据插入第 2 个分区,也就是 p2 分区

INSERT INTO systab PARTITION (2) VALUES (7,8);

-- 为了实现绑定变量,用 pno 变量来代替实际分区号,以避免过度解析

INSERT INTO systab PARTITION (:pno) VALUES (9,10);

由于 System  Partitioning  的特殊性,所以很明显,这种类型的分区将不支持

Partition Split 操作,也不支持 create table as select 操作。


1.3 More Composite Partitioning

在 10g 中,我们知道复合分区只支持 Range-List 和 Range-Hash,而在 11g 中复合分区的类型大大增加,现在 Range,List,Interval 都可以作为 Top level 分区,而 Second level 则可以是 Range,List,Hash,也就是在 11g 中可以有 3*3=9种复合分区,满足更多的业务需求。


1.4 Virtual Column-Based Partitioning

Virtual Column 是 11g 中的一个新功能,这种列中的数据并不实际存储于磁盘上(我们可以看成是一个类似 Function 的列),只有当读取的时候才实时计算。 暂时不讨论性能问题,这个功能还是比较有意思的。

可以通过这样的语句来创建虚拟列。

CREATE TABLE tb_v (

col_1 number(6) not null,

col_2 number not null,

col_v as (col_1 *( 1+col_2)

);

虚拟列虽然没有实际的存储空间,但是却可以跟其他普通列一样,创建索引, 作为分区键,甚至可以收集统计信息。

1.5  11g 虚拟列实现按星期分区表

在 11g 之前分区表的 partition key 必须是物理存在的。 11g 开始提供了虚拟 列,并且可以作为 partition key 。

1. 创建分区表:

CREATE TABLE PT

(

getdate      date NOT NULL,

wd                   NUMBER GENERATED ALWAYS AS (TO_NUMBER (TO_CHAR

(getdate, 'D'))) VIRTUAL --虚拟列

)

PARTITION BY LIST (wd)

(PARTITION Sun   VALUES (1),


PARTITION Mon

VALUES (2),

PARTITION Tue

VALUES (3),

PARTITION Wed

VALUES (4),

PARTITION Thu

VALUES (5),

PARTITION Fri

VALUES (6),

PARTITION Sat

VALUES (7)

);


2. 插入测试数据

SQL> insert into pt(getdate) values(sysdate);

已创建 1 行。

SQL> insert into pt(getdate) values(sysdate-1);

已创建 1 行。

SQL> insert into pt(getdate) values(sysdate-2);

已创建 1 行。

SQL> insert into pt(getdate) values(sysdate-3);

已创建 1 行。

SQL> insert into pt(getdate) values(sysdate-4);

已创建 1 行。

SQL> insert into pt(getdate) values(sysdate-5);

已创建 1 行。

SQL> insert into pt(getdate) values(sysdate-6);

已创建 1 行。

SQL> insert into pt(getdate) values(sysdate-7);

已创建 1 行。

SQL> commit;

提交完成。

3. 查看数据:


SQL> select * from pt;

GETDATE

WD

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

06-6  -10

1

07-6  -10

2

08-6  -10

3

09-6  -10

4

10-6  -10

5

03-6  -10

5

04-6  -10

6

05-6  -10

7


已选择 8 行。

SQL> alter session set nls_date_format='YYYY-MM-DD';


会话已更改。

SQL> select * from pt;

GETDATE

WD

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

2010-06-06

1

2010-06-07

2

2010-06-08

3

2010-06-09

4

2010-06-10

5

2010-06-03

5

2010-06-04

6

2010-06-05

7

已选择 8 行。


4. 查看每个分区里的内容:

SQL> select * from pt partition(sun);

GETDATE                    WD

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

2010-06-06                 1

SQL> select * from pt partition(mon);

GETDATE                    WD

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

2010-06-07                 2

SQL> select * from pt partition(tue);

GETDATE                    WD

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

2010-06-08                 3

SQL> select * from pt partition(wed);

GETDATE                    WD

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

2010-06-09                 4

SQL> select * from pt partition(fri);

GETDATE                    WD

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

2010-06-04                 6

SQL> select * from pt partition(sat);

GETDATE                    WD

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

2010-06-05                 7

SQL>

注:如果是 10g,就要添加一物理列。


1.5.1  Interval 分区示例

在 Oracle Database 11g 中还可以创建新类型的Interval 分区表,Interval 类型分区表,可以根据加载数据,自动创建指定间隔的分区。


1.5.1.1 创建按月分区的分区表

1. 创建分区表

/* Formatted on 2010/6/10 20:21:12 (QP5 v5.115.810.9015) */ 

create table intervalpart (c1 number, c3 date)

partition by range (c3)

interval ( numtoyminterval (1, 'month') )

 (partition part1

values less than (to_date ('01/12/2010', 'mm/dd/yyyy')),

partition part2

values less than (to_date ('02/12/2010', 'mm/dd/yyyy'))

)

注意:如果在建 Interval 分区表是没有把所有的分区写完成,在插入相关数据后会自动生成分区

2. 查看现在表的分区:

SQL>     select    table_name,partition_name    from    user_tab_partitions    where

table_name='INTERVALPART';

TABLE_NAME                                         PARTITION_NAME

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

INTERVALPART                                    PART1

INTERVALPART                                    PART2

3.        插入测试数据: 

SQL> begin

2    for i in 0 .. 11 loop

3 insert into intervalpart values(i,add_months(to_date('2010-1-1','yyyy-mm-dd'),i));

4        end loop ;

5        commit;

6        end;

7        /

PL/SQL 过程已成功完成。

补充:add_months() 函数获取前一个月或者下一个月的月份, 参数中 负数 代 表 往前, 正数 代表 往后。

--上一个月

select to_char(add_months(trunc(sysdate),-1),'yyyymm') from dual;

--下一个月

select to_char(add_months(trunc(sysdate),1),'yyyymm') from dual;

4. 观察自动创建的分区:


SQL>

select

table_name,partition_name   from   user_tab_partitions   where

table_name='INTERVALPART';

TABLE_NAME

PARTITION_NAME

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

INTERVALPART

PART1

INTERVALPART

PART2

INTERVALPART

SYS_P22

INTERVALPART

SYS_P23

INTERVALPART

SYS_P24

INTERVALPART

SYS_P25

INTERVALPART

SYS_P26

INTERVALPART

SYS_P27

INTERVALPART

SYS_P28

INTERVALPART

SYS_P29

INTERVALPART

SYS_P30

INTERVALPART

SYS_P31


已选择 12 行。

5. 查看分区内容:

SQL> select * from INTERVALPART;

C1 C3

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

1  2010-01-01

0  2010-01-01

1  2010-02-01

2  2010-03-01

3  2010-04-01

4  2010-05-01

5  2010-06-01

6  2010-07-01

7  2010-08-01

8  2010-09-01

9  2010-10-01

10  2010-11-01

11  2010-12-01

已选择 13 行。


SQL> select * from INTERVALPART partition(part1);

C1 C3

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

1 2010-01-01

0 2010-01-01

SQL> select * from INTERVALPART partition(part2);

 C1 C3

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

1  2010-02-01


1.5.1.2  创建一个以天为间隔的分区表 


1. 创建分区表:

SQL> create table dave


2

(

3

id

number,

4

dt

date


5        )

6        partition by range (dt)

7        INTERVAL (NUMTODSINTERVAL(1,'day'))

8        (

9        partition p100101 values less than (to_date('2010-01-01','yyyy-mm-dd'))

10 );

2. 查看表分区:

SQL> select table_name,partition_name from user_tab_partitions where table_name='DAVE';

TABLE_NAME                                    PARTITION_NAME

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

DAVE                                              P100101


3. 插入测试数据:

SQL> begin

2    for i in 1 .. 12 loop

3        insert into dave values(i,trunc(to_date('2010-1-1','yyyy-mm-dd')+i));

4        end loop;

5        commit;

6        end;

7        /

PL/SQL 过程已成功完成。

4. 观察自动创建的分区:

SQL>     select    table_name,partition_name    from    user_tab_partitions    where

table_name='DAVE';

TABLE_NAME                                         PARTITION_NAME

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

DAVE                                                     P100101

DAVE                                                     SYS_P32

DAVE                                                     SYS_P33

DAVE                                                     SYS_P34

DAVE                                                     SYS_P35

DAVE                                                     SYS_P36

DAVE                                                     SYS_P37

DAVE                                                     SYS_P38

DAVE                                                     SYS_P39

DAVE                                                     SYS_P40

DAVE                                                     SYS_P41

DAVE                                                     SYS_P42

DAVE                                                     SYS_P43

已选择 13 行。

5. 查看分区内容:

SQL> select * from dave partition(SYS_P32);


ID DT

---------- ----------
1 2010-01-02

SQL> select * from dave partition(SYS_P33); I


D DT

---------- ----------
2 2010-01-03

SQL> select * from dave partition(SYS_P34);


ID DT

---------- ----------
3 2010-01-04

SQL> select * from dave;

ID DT

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

1  2010-01-02

2  2010-01-03

3  2010-01-04

4  2010-01-05

5  2010-01-06

6  2010-01-07

7  2010-01-08

8  2010-01-09

9  2010-01-10

10  2010-01-11

11  2010-01-12

12  2010-01-13

已选择 12 行。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29345367/viewspace-1816436/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29345367/viewspace-1816436/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值