您的位置:首页 > 数据库 > Oracle

Oracle Partition分区简介

2015-06-28 17:13 423 查看
一、Oracle分区简介

ORACLE的分区是一种处理超大型表、索引等的技术。分区是一种“分而治之”的技术,通过将大表和索引分成可以管理的小块,从而避免了对每个表作为一个大的、单独的对象进行管理,为大量数据提供了可伸缩的性能。分区通过将操作分配给更小的存储单元,减少了需要进行管理操作的时间,并通过增强的并行处理提高了性能,通过屏蔽故障数据的分区,还增加了可用性。

二、Oracle分区优缺点

优点:

增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;

维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;

均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能;

改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。

缺点:

分区表相关:已经存在的表没有方法可以直接转化为分区表。不过Oracle提供了在线重定义表的功能。

三、Oracle分区方法

范围分区:

范围分区就是对数据表中的某个值的范围进行分区,根据某个值的范围,决定将该数据存储在哪个分区上。如根据序号分区,根据业务记录的创建日期进行分区等。

Hash分区(散列分区):

散列分区为通过指定分区编号来均匀分布数据的一种分区类型,因为通过在I/O设备上进行散列分区,使得这些分区大小一致。

List分区(列表分区):

当你需要明确地控制如何将行映射到分区时,就使用列表分区方法。与范围分区和散列分区所不同,列表分区不支持多列分区。如果要将表按列分区,那么分区键就只能由表的一个单独的列组成,然而可以用范围分区或散列分区方法进行分区的所有的列,都可以用列表分区方法进行分区。

范围-散列分区(复合分区):

有时候我们需要根据范围分区后,每个分区内的数据再散列地分布在几个表空间中,这样我们就要使用复合分区。复合分区是先使用范围分区,然后在每个分区内再使用散列分区的一种分区方法(注意:先一定要进行范围分区)

范围-列表分区(复合分区):

范围和列表技术的组合,首先对表进行范围分区,然后用列表技术对每个范围分区再次分区。与组合范围-散列分区不同的是,每个子分区的所有内容表示数据的逻辑子集,由适当的范围和列表分区设置来描述。(注意:先一定要进行范围分区)

四、Oracle表分区表操作

--Partitioning是否为true

select*fromv$optionsorderbys.PARAMETERdesc

--创建表空间

CREATETABLESPACE"PARTION_03"

LOGGING

DATAFILE'D:\ORACLE\ORADATA\JZHUA\PARTION_03.dbf'SIZE50M

EXTENTMANAGEMENTLOCALSEGMENTSPACEMANAGEMENTAUTO

--删除表空间

droptablespacepartion_01

--范围分区技术

createtablePartition_Test

(

PIDnumbernotnull,

PITEMvarchar2(200),

PDATAdatenotnull

)

partitionbyrange(PID)

(

partitionpart_01valueslessthan(50000)tablespacedinya_space01,

partitionpart_02valueslessthan(100000)tablespacedinya_space02,

partitionpart_03valueslessthan(maxvalue)tablespacedinya_space03

)

createtablePartition_TTest

(

PIDnumbernotnull,

PITEMvarchar2(200),

PDATAdatenotnull

)

partitionbyrange(PDATA)

(

partitionpart_t01valueslessthan(to_date('2004-01-01','yyyy-mm-dd'))tablespacedinya_space01,

partitionpart_t02valueslessthan(to_date('2008-01-01','yyyy-mm-dd'))tablespacedinya_space02,

partitionpart_t03valueslessthan(maxvalue)tablespacedinya_space03

)

insertintoPartition_Test(PID,PITEM,PDATA)selecth.id,h.userid,h.rectimefromst_handleh

select*fromPartition_Testpartition(part_01)twheret.pid='1961'

--hash分区技术

createtablePartition_HashTest

(

PIDnumbernotnull,

PITEMvarchar2(200),

PDATAdatenotnull

)

partitionbyhash(PID)

(

partitionpart_h01tablespacedinya_space01,

partitionpart_h02tablespacedinya_space02,

partitionpart_h03tablespacedinya_space03

)

insertintoPartition_HashTest(PID,PITEM,PDATA)selecth.id,h.userid,h.rectimefromst_handleh

select*fromPartition_HashTestpartition(part_h03)twheret.pid='1961'

--复合分区技术

createtablePartition_FHTest

(

PIDnumbernotnull,

PITEMvarchar2(200),

PDATAdatenotnull

)

partitionbyrange(PDATA)subpartitionbyhash(PID)subpartitions3storein(dinya_space01,dinya_space02,dinya_space03)

(

partitionpart_fh01valueslessthan(to_date('2004-01-01','yyyy-mm-dd'))tablespacedinya_space01,

partitionpart_fh02valueslessthan(to_date('2008-01-01','yyyy-mm-dd'))tablespacedinya_space02,

partitionpart_fh03valueslessthan(maxvalue)tablespacedinya_space03

)

insertintoPartition_FHTest(PID,PITEM,PDATA)selecth.id,h.userid,h.rectimefromst_handleh

select*fromPartition_FHTestpartition(part_fh02)twheret.pid='1961'

select*fromPartition_FHTestpartition(part_fh03)t

--速度比较

select*fromst_handlehwhereh.rectime>to_date('2008-01-01','yyyy-mm-dd');

select*fromPartition_FHTestpartition(part_fh03)twheret.pdata>to_date('2008-01-01','yyyy-mm-dd');

--分区表操作

--增加一个分区

altertablePartition_Testaddpartitionpart_05valueslessthan(10020)tablespacedinya_space03

--查询分区数据

select*fromPartition_FHTestpartition(part_fh02)t

--修改分区里的数据

updatePartition_FHTestpartition(part_fh02)tsett.PITEM='JZHUA'wheret.pid='1961'

--删除分区里的数据

deletefromPartition_FHTestpartition(part_fh02)twheret.pid='1961'

--合并分区

createtablePartition_HB

(

PIDnumbernotnull,

PITEMvarchar2(200),

PDATAdatenotnull

)

partitionbyrange(PID)

(

partitionpart_01valueslessthan(50000)tablespacedinya_space01,

partitionpart_02valueslessthan(100000)tablespacedinya_space02,

partitionpart_03valueslessthan(maxvalue)tablespacedinya_space03

)

insertintoPartition_HB(PID,PITEM,PDATA)selecth.id,h.userid,h.rectimefromst_handleh

select*fromPartition_HBpartition(part_03)twheret.pid='100001'

altertablePartition_HBmergepartitionspart_01,part_02intopartitionpart_02;

--拆分分区

--spiltpartition分区名at(这里是一个临界区,比如:50000就是说小于50000的放在part_01,而大于50000的放在part_02中)

altertablePartition_HBsplitPartitionpart_02at(50000)into(Partitionpart_01tablespacedinya_space01,Partitionpart_02tablespacedinya_space02);

--更改分区名

altertablePartition_HBrenamePartitionpart_01_testtopart_02;

五、Oracle索引分区表操作

分区表和一般表一样可以建立索引,分区表可以创建局部索引和全局索引。当分区中出现许多事务并且要保证所有分区中的数据记录的唯一性时采用全局索引。全局索引建立时global子句允许指定索引的范围值,这个范围值为索引字段的范围值。其实理论上有3中分区索引。

Global索引(全局索引):

对于global索引,可以选择是否分区,而且索引的分区可以不与表分区相对应。当对分区进行维护操作时,通常会导致全局索引的Invalid,必须在执行完操作后Rebuild。Oracle9i提供了UpdateGlobalIndexes语句,可以在进行分区维护的同时重建全局索引。

1:索引信息的存放位置与父表的Partition(分区)信息完全不相干。甚至父表是不是分区表都无所谓的。

createindexdinya_idx_tondinya_test(item_id)globalpartitionbyrange(item_id)(

partitionidx_1valueslessthan(1000)tablespacedinya_space01,

partitionidx_2valueslessthan(10000)tablespacedinya_space02,

partitionidx_3valueslessthan(maxvalue)tablespacedinya_space03

);

2:但是在这种情况下,如果父表是分区表,要删除父表的一个分区都必须要更新GlobalIndex,否则索引信息不正确

ALTERTABLETableNameDROPPARTITIONPartitionNameUpdateGlobalIndexes

Local索引(局部索引):

对于local索引,每一个表分区对应一个索引分区(就是说一个分区表一个字段只可以建一个局部索引),当表的分区发生变化时,索引的维护由Oracle自动进行;

1:索引信息的存放位置依赖于父表的Partition(分区)信息,换句话说创建这样的索引必须保证父表是Partition(分区),索引信息存放在父表的分区所在的表空间。

2:但是仅可以创建在父表为HashTable或者composite分区表的。

3:仅可以创建在父表为HashTable或者composite分区表的。并且指定的分区数目要与父表的分区数目要一致。

createindexdinya_idx_tondinya_test(item_id)local(

partitionidx_1tablespacedinya_space01,

partitionidx_2tablespacedinya_space02,

partitionidx_3tablespacedinya_space03

);

不指定索引分区名直接对整个表建立索引

createindexdinya_idx_tondinya_test(item_id);

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

ORACLE为构建数据仓库提供了4种类型的分区方法:RangePartition,HashPartition,ListPartition,CompositePartition.

下面我分别对这四种分区方法的概念,他们的使用场景,以及各种分区方法做一个性能比较。

一:概念

1:RangePartitioning

这是最常用的一种分区方法,基于COLUMN的值范围做分区,最常见的是基于时间字段的数据的范围的分区,比如:对于SALE表,可以对销售时间按照月份做一个RangePartitioning。这种分区在数据仓库里用的比较多,以下是CREATESTATMENT

CREATETABLEsales_range

(salesman_idNUMBER(5),

salesman_nameVARCHAR2(30),

sales_amountNUMBER(10),

sales_dateDATE)

COMPRESS

PARTITIONBYRANGE(sales_date)

(PARTITIONsales_jan2000VALUESLESSTHAN(TO_DATE('02/01/2000','DD/MM/YYYY')),

PARTITIONsales_feb2000VALUESLESSTHAN(TO_DATE('03/01/2000','DD/MM/YYYY')),

PARTITIONsales_mar2000VALUESLESSTHAN(TO_DATE('04/01/2000','DD/MM/YYYY')),

PARTITIONsales_apr2000VALUESLESSTHAN(TO_DATE('05/01/2000','DD/MM/YYYY')));

对于COMPRESS关键字的理解,将在后续的压缩分区讲到

2;HashPartitioning

HashPartitioning映射数据到基于HASH算法的分区上,HASH算法将应用你指定的分区关键字,平均的分那些在Partitions中的行。给每一个分区近似相同的大小,要保证数据能平均分配,分区数一般是2N。比如说,需要insertsales_hash一条数据,ORACLE会通过HASH算法处理salesman_id,然后找到对于的分区表进行insert。HashPartitioning是为跨越设备的分布式数据提供了一种理想的方法,HASH算法也很容易转化成RANGE分区方法,特别是当被分区的数据不是历史数据时。

CREATETABLEsales_hash

(salesman_idNUMBER(5),

salesman_nameVARCHAR2(30),

sales_amountNUMBER(10),

week_noNUMBER(2))

PARTITIONBYHASH(salesman_id)

PARTITIONS4;

3:ListPartitioning

ListPartitioning能够让你明确的控制有多少行被分区,你能对要分区的COLUMN上明确的指定按照那些具体的值来分区,这种方式在Range和Hash方式是做不到的。这种方式的优点是,你能组织和分组那些没有顺序和没有关系的数据集。下面是通过销售地区做一个List分区表。

CREATETABLEsales_list

(salesman_idNUMBER(5),

salesman_nameVARCHAR2(30),

sales_stateVARCHAR2(20),

sales_amountNUMBER(10),

sales_dateDATE)

PARTITIONBYLIST(sales_state)

(PARTITIONsales_westVALUES('California','Hawaii')COMPRESS,

PARTITIONsales_eastVALUES('NewYork','Virginia','Florida'),

PARTITIONsales_centralVALUES('Texas','Illinois'));

4:CompositePartitioning

CompositePartitioning是把Range,Hash,List分区方式组合起来的分区方式。

比如CompositeRange-HashPartitioning和CompositeRange-ListPartitioning:

CREATETABLEsales_range_hash(

s_productidNUMBER,

s_saledateDATE,

s_custidNUMBER,

s_totalpriceNUMBER)

PARTITIONBYRANGE(s_saledate)

SUBPARTITIONBYHASH(s_productid)SUBPARTITIONS8

(PARTITIONsal99q1VALUESLESSTHAN(TO_DATE('01-APR-1999','DD-MON-YYYY')),

PARTITIONsal99q2VALUESLESSTHAN(TO_DATE('01-JUL-1999','DD-MON-YYYY')),

PARTITIONsal99q3VALUESLESSTHAN(TO_DATE('01-OCT-1999','DD-MON-YYYY')),

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

另外你还可以用subpartitiontemplate的方式指定:

CREATETABLEsales_range_hash(

s_productidNUMBER,

s_saledateDATE,

s_custidNUMBER,

s_totalpriceNUMBER)

PARTITIONBYRANGE(s_saledate)

SUBPARTITIONBYHASH(s_productid)

SUBPARTITIONTEMPLATE(

SUBPARTITIONsp1TABLESPACEtbs1,

SUBPARTITIONsp2TABLESPACEtbs2,

SUBPARTITIONsp3TABLESPACEtbs3,

SUBPARTITIONsp4TABLESPACEtbs4,

SUBPARTITIONsp5TABLESPACEtbs5,

SUBPARTITIONsp6TABLESPACEtbs6,

SUBPARTITIONsp7TABLESPACEtbs7,

SUBPARTITIONsp8TABLESPACEtbs8)

(PARTITIONsal99q1VALUESLESSTHAN(TO_DATE('01-APR-1999','DD-MON-YYYY')),

PARTITIONsal99q2VALUESLESSTHAN(TO_DATE('01-JUL-1999','DD-MON-YYYY')),

PARTITIONsal99q3VALUESLESSTHAN(TO_DATE('01-OCT-1999','DD-MON-YYYY')),

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

这样,没有子分区通过的HASH分区将会统一到不同的表空间。

二:使用各种分区方法的场景

1:什么时候用RangePartition

RangePartition是一种方便的方法分区历史的数据,经常在DATECOLMUN通过时间间隔组织数据。比如说:你要查询2009年8月的数据,查询将直接找到2009年8月的分区,避免了大量不必要的数据扫描。

在处理周期性的load新数据和purge老数据的时候,RangePartition也是一个理想的选择。

应用场景:

a)有一个大表需要通过时间字段频繁的访问,通过这个时间字段做RANGPARTITION有利于做分区裁剪。

b)如果你不能对一个大表在指定的时间内做备份或RESTORE,你可以通过RANGE把他们分成小的logic片来做。

2:什么时候用HASHPartition

HASHPartition不是一个很好的管理历史的方法。

应用场景

a)增加大表的可用性。

b)避免各个分区之间查找数据,并且各个分区可以放在不同的设备上,达到最大的I0吞吐量。也可以用STOREIN子句分配每个分区到不同的表空间。

3:什么时候用LISTPartition

如果你想映射数据到离散的值的时候,LISTPartition是个比较好的选择。

4:什么时候用CompositeRange-HashPartitioning

这是Range和Hash的组合使用,先对表用RANGE分,然后对每个RANGE再做HASH分区。

由于做了RANGE后的子分区是没有规律的,如果在数据仓库设计时候,通过查询需求觉得有必要再细分,可以考虑使用。ORACLE会把子分区又分成不同的SEGMENT。

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

和PARTITION有关的视图有:

--分区表相关视图

DBA_PART_TABLES

ALL_PART_TABLES

USER_PART_TABLES

DBA_TAB_PARTITIONS

ALL_TAB_PARTITIONS

USER_TAB_PARTITIONS

DBA_TAB_SUBPARTITIONS

ALL_TAB_SUBPARTITIONS

USER_TAB_SUBPARTITIONS

DBA_PART_KEY_COLUMNS

ALL_PART_KEY_COLUMNS

USER_PART_KEY_COLUMNS

DBA_SUBPART_KEY_COLUMNS

ALL_SUBPART_KEY_COLUMNS

USER_SUBPART_KEY_COLUMNS

DBA_PART_COL_STATISTICS

ALL_PART_COL_STATISTICS

USER_PART_COL_STATISTICS

DBA_SUBPART_COL_STATISTICS

ALL_SUBPART_COL_STATISTICS

USER_SUBPART_COL_STATISTICS

DBA_PART_HISTOGRAMS

ALL_PART_HISTOGRAMS

USER_PART_HISTOGRAMS

DBA_SUBPART_HISTOGRAMS

ALL_SUBPART_HISTOGRAMS

USER_SUBPART_HISTOGRAMS

DBA_PART_INDEXES

ALL_PART_INDEXES

USER_PART_INDEXES

DBA_IND_PARTITIONS

ALL_IND_PARTITIONS

USER_IND_PARTITIONS

DBA_IND_SUBPARTITIONS

ALL_IND_SUBPARTITIONS

USER_IND_SUBPARTITIONS

DBA_SUBPARTITION_TEMPLATES

ALL_SUBPARTITION_TEMPLATES

USER_SUBPARTITION_TEMPLATES


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

Hashpartitioningisapartitioningtechniquewhere
ahashkeyisusedtodistributerowsevenly
acrossthedifferentpartitions(sub-tables).Thisistypicallyusedwhererangesaren'tappropriate,i.e.employeenumber,productID,etc.


[edit]History

HashpartitioningwasfirstintroducedinOracle8i.


[edit]Examples

createtableemp2(
empnonumber(4),
enamevarchar2(30),
salnumber
)
partitionbyhash(empno)(
partitione1tablespaceemp1,
partitione2tablespaceemp2,
partitione3tablespaceemp3,
partitione4tablespaceemp4
);

createtableemp2(
empnonumber(4),
enamevarchar2(30),
salnumber
)
PARTITIONBYHASH(empno)
PARTITIONS3
STOREIN(empts1,empts2,empts3);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: