Chinaunix首页 | 论坛 | 博客
  • 博客访问: 435645
  • 博文数量: 55
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1584
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-04 15:15
个人简介

热衷技术,热爱交流

文章分类

全部博文(55)

文章存档

2014年(7)

2013年(48)

分类: Oracle

2013-06-20 20:56:59

  

分区



1  什么是分区


把一个大的表或者索引分成一些小的片段,这些片段就叫做分区。

如果一个表中的数据量巨大时,可以将此表设计成分区表,提高查询性能和可管理性。表分区有多种,使用最多的是范围分区(range partition)。

范围分区是指根据表中的某一列(创建分区表时指定的分区键-Partition Key)的取值范围,将数据分布到不同的分区中。分区可以位于同一个表空间,也可以位于单独的表空间。常见的是按时间分区。

例如:

create table ok_EVENT

(

  event_id                   NUMBER(20) not null,

  end_time                 TIMESTAMP(3) not null,

  uuid                       VARCHAR2(8) not null,

)

partition by range (END_TIME)

(

  partition P20060324 values less than (TIMESTAMP' 2006-03-25 00:00:00')   tablespace ok20060324,

  partition P20120907 values less than (TIMESTAMP' 2012-09-08 00:00:00')   tablespace ok20120907,

  partition P20120908 values less than (TIMESTAMP' 2012-09-09 00:00:00')   tablespace ok20120908

)

在上例中,ok_event表的end_time列作为分区键划分为3个分区,三个分区位于不同的表空间。当插入数据的时候,可以像对待普通的表一样使用insert语句,根据插入语句中end_time列的值决定数据插入到哪个分区,落在哪个分区内便插入哪个分区。如果没有命中任何分区,oracle会报错,插入失败。

各个分区不一定非要存放到单独的表空间,完全可以放到同一个表空间里。对于分区越来越多的情形,使用单独的表空间更方便管理。

 

2   为什么使用分区?


1.      
易于管理和维护:

在分区中,可以对单独的分区进行进行数据加载、备份、恢复以及索引的重建等。分区技术可以看做将大表分割成一个一个小表,小表总要比大表管理起来方便。比如一个按时间(天)分区的表,如果想删除某一天的数据,常规表的办法是使用delete,当这一天含有大量数据时,delete相当费时,且要占用大量的系统资源(比如生成大量的redo logundo),而且不会释放系统文件的大小。如果采用分区表,只需要drop掉该天对应的分区即可,这是ddl操作,瞬间完成,只生成少量的redoundo,而且可以回收空间。再如,当把分区放在不同的表空间上,当其中某一个分区的文件丢失或损坏时,只需要将该表空间离线即可,只对查询该分区数据的操作有影响,这称为分区消除。相反,如果是一个普通表,如果文件损坏,整个表都无法访问了。

2.       提高查询性能:

查询的时候可以查询指定分区的数据,就像查一张小表一样。另外,通过在where条件中使用分区键,可以将数据的扫描范围锁定在where条件限定的分区内,而不是扫描整个大表。这对于查询条件多样、索引有限、返回结果集巨大的系统带来很大好处。

分区表一般使用局部索引(local),一个表分区对应一个索引分区,由oracle自动维护。每个索引分区可以单独管理(如重建),大大方便了管理。

3.       OLTP 系统中减少对共享资源的争用

设想,有多个用户在查询一个表,在没有使用分区的情况下,即使用户查询条件不一样,oracle始终是在访问一个文件。使用了分区,把不同时间段的数据放在不同数据文件,这样不同查询条件就可以访问不同的文件了。


3  分区策略


从单一分方式(single-level)考虑,分区策略包括范围分区(range partition),列表分区(list partition),哈希分区(hash paritition)。分区策略还可以使用复合方式(composite partitioning),例如,可以首先采用第一种数据分配方式进行分区,在此基础上,再使用第二种数据分布方式进行子分区,这类似复合条件的排序。


4   分区操作


 范围分区:


前面已经谈到范围分区了。范围分区键值中确定各个分区范围最高点叫跃点(transition point


数据库为超过跃点的值确定间隔分区(interval partition). 当插入到表中的数据超出所有已定义的表分区时,间隔分区指示数据库自动创建特定范围或特定间隔的分区,来扩展范围分区。

SYS >create tablespace hr_pt datafile '/u01/oradata2/hx/hr_pt.dbf'

 SIZE 100M REUSE AUTOEXTEND ON NEXT 128M  MAXSIZE  UNLIMITED;;

HR >create table test_pt(end_time date)

NOLOGGING

PARTITION BY RANGE (END_TIME)

         (

          PARTITION P20060323 VALUES LESS THAN (TO_DATE('2006-03-24 00:00:00','yyyy-mm-dd hh24:mi:ss'))

          NOLOGGING

          TABLESPACE hr_pt

          );

insert into test_pt values('2006-04-24 00:00:00');            *

ERROR at line 1:

ORA-14400: 插入的分区关键字未映射到任何分区


CREATE TABLE time_range_sales

   ( prod_id        NUMBER(6)

   , cust_id        NUMBER

   , time_id        DATE

   , channel_id     CHAR(1)

   , promo_id       NUMBER(6)

   , quantity_sold  NUMBER(3)

   , amount_sold    NUMBER(10,2)

   )

PARTITION BY RANGE (time_id)

 (PARTITION SALES_1998 VALUES LESS THAN

(TO_DATE('01-JAN-1999','DD-MON-YYYY')),

  PARTITION SALES_1999 VALUES LESS THAN

(TO_DATE('01-JAN-2000','DD-MON-YYYY')),

  PARTITION SALES_2000 VALUES LESS THAN

(TO_DATE('01-JAN-2001','DD-MON-YYYY')),

);

HR >select * from time_range_sales partition(SALES_1998);


   PROD_ID|   CUST_ID|TIME_ID            |C|  PROMO_ID|QUANTITY_SOLD|AMOUNT_SOLD

----------|----------|-------------------|-|----------|-------------|-----------

       116|     11393|1998-11-10 00:00:00|2|       999|            1|      12.18

       116|     11393|1997-11-10 00:00:00|2|       999|            1|      12.18

       116|     11393|1996-11-10 00:00:00|2|       999|            1|      12.18


HR >alter table  time_range_sales add PARTITION SALES_2001 VALUES LESS THAN (MAXVALUE);

HR >insert into  TIME_RANGE_SALES  values(116,      11393, to_date('2012-11-10','yyyy-mm-dd'), '2',999, 1, 12.18) ;;

HR >select * from time_range_sales partition(SALES_2001);

   PROD_ID|   CUST_ID|TIME_ID            |C|  PROMO_ID|QUANTITY_SOLD|AMOUNT_SOLD

----------|----------|-------------------|-|----------|-------------|-----------

       116|     11393|2012-11-10 00:00:00|2|       999|            1|      12.18


列表分区


列表分区很简单,与范围分区有些类似,它的实质就是把满足一些值的特定行放在一定的分区,如果上面的范围分区是按照连续区间进行分区,那么列表分区就是按照不连续区间,也就是枚举方式进行分区:

SIM >create tablespace list_partition datafile '/u01/oradata2/hx/list_partition.dbf' size 10m;

SIM >create tablespace list_partition02 datafile'/u01/oradata2/hx/list_partition02.dbf' size 10m;

HR >create table list_partition(id number(10))

partition by list (id)

(partition list_partition values(1,2,3) tablespace LIST_PARTITION,

partition list_partition02 values(4,5,6) tablespace LIST_PARTITION02);

HR >insert into list_partition values(1);

HR >insert into list_partition values(4);

HR >select * from list_partition partition(list_partition);

        ID

----------

         1

HR >select * from list_partition partition(list_partition02);

       ID

----------

         4

如果插入的值是特定的,并且经常需要用这些值查询,而且这个分区键是一个重要字段,可能会用到列表分区。


        哈希分区


在哈希分区中,基于用户所指定的将在分区键上应用的哈希算法,数据库将行映射到各个分区。行的目标分区是由数据库应用于行的内部哈希函数所决定的。哈希算法被设计为可以跨设备均匀分布行,以使每个分区包含大致相同同的行数。如果单纯考虑均匀分布行,不考虑按照日期,或者枚举值进行分区,哈希分区是个好办法。

HR >create table hash_partition(id number(10))

  partition by hash (id)

  partitions 3;  --建表,指定行在三个分区之间均匀分布

Table created.

HR >select table_name,partition_name from user_tab_partitions where TABLE_NAME='HASH_PARTITION';


TABLE_NAME                    |PARTITION_NAME

------------------------------|------------------------------

HASH_PARTITION                |SYS_P243

HASH_PARTITION                |SYS_P244

HASH_PARTITION                |SYS_P245

HR >insert into HASH_PARTITION values(100);


HR >insert into HASH_PARTITION values(200);


HR >insert into HASH_PARTITION values(300);


HR >select * from HASH_PARTITION partition(SYS_P243);


        ID

----------

       200


Elapsed: 00:00:00.02

HR >select * from HASH_PARTITION partition(SYS_P244);


        ID

----------

       300


Elapsed: 00:00:00.02

HR >select * from HASH_PARTITION partition(SYS_P245);


        ID

----------

       100


Elapsed: 00:00:00.01

HR >select SEGMENT_NAME,PARTITION_NAME,TABLESPACE_NAME from user_segments where segment_name='HASH_PARTITION';


SEGMENT_NAME             |PARTITION_NAME                |TABLESPACE_NAME

-------------------------|------------------------------|--------------------

HASH_PARTITION           |SYS_P243                      |HR

HASH_PARTITION           |SYS_P245                      |HR

HASH_PARTITION           |SYS_P244                      |HR

思考:

1.有一个表很重要,每天数据用一个分区存放,并且指定一个特定表空间。

2.表空间和分区生成方式如下:表中有一个属性叫做end_time,这个值正好等于行插入时的系统时间,就把他当作分区键。每周日晚上九点生成接下来七天的表空间和分区,这样接下来 七天的数据都可以插入了。

3. 如果某周日晚上九点这个点,数据库关闭,造成计划任务没能运行,那么数据库启动后必须要及时生成表空间和分区,使得新数据可以插入。

4.一旦系统时间改变,可能会存在无法插入数据的情况。所以改变时间后必须要保证及时生成最新一周的表空间和分区

阅读(2390) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~