2023年11月26日发(作者:)

[]

三思笔记全面学习分区表及分区索引

2008-04-15

.............................................2008-04-15关于分区表和分区索引

2008-04-17WHEN.......................................................................

When使用Range分区

When使用Hash分区

When使用List分区

When使用组合分区

HOW.......................................................................2008-04-23

如何创建

创建range分区

创建hash分区

创建list分区

创建range-list分区

创建range-hash分区

公共准则

如何管理

管理表分区

增加表分区(addpartition)

收缩表分区(coalescepartitions)

删除表分区(droppartition)

交换表分区(ExchangePartitions)

合并表分区(MergePartitions)

修改list表分区--Add/DropValues

拆分表分区(SplitPartition)

截断表分区(TruncatePartition)

移动表分区(MovePartition)

重命名表分区(RenamePartition)

修改表分区默认属性(ModifyDefaultAttributes)

修改表分区当前属性(ModifyPartition)

管理索引分区

增加索引分区(AddingIndexPartitions)

删除索引分区(DroppingIndexPartitions)

重编译索引分区(RebuildingIndexPartitions)

重命名索引分区(RenamingIndexPartitions)

拆分索引分区(SplittingIndexPartitions)

修改索引分区默认属性(ModifyingDefaultAttributesofIndexPartitions)

修改索引分区当前属性(ModifyingRealAttributesofIndexPartitions)

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

关于分区表和分区索引(AboutPartitionedTablesandIndexes)

对于10gR2而言,基本上可以分成几类:

Range(范围)分区

Hash(哈希)分区

List(列表)分区

以及组合分区:Range-Hash,Range-List

对于表而言(常规意义上的堆组织表),上述分区形式都可以应用(甚至可以对某个分区指定compress属性)

只不过分区依赖列不能是lob,long之类数据类型,每个表的分区或子分区数的总数不能超过1024K-1个。

对于索引组织表,只能够支持普通分区方式,不支持组合分区,常规表的限制对于索引组织表同样有效,

除此之外呢,还有一些其实的限制,比如要求索引组织表的分区依赖列必须是主键才可以等。

注:本篇所有示例仅针对常规表,即堆组织表!

对于索引,需要区分创建的是全局索引,或本地索引:

全局索引(globalindex):即可以分区,也可以不分区。即可以建range分区,也可以建hash分区,

即可建于分区表,又可创建于非分区表上,就是说,全局索引是完全独立的,因此它也需要我们更多的维

护操作。

本地索引(localindex):其分区形式与表的分区完全相同,依赖列相同,存储属性也相同。对于本

地索引,其索引分区的维护自动进行,就是说你add/drop/split/truncate表的分区时,本地索引会自动维护其

索引分区。

Oracle建议如果单个表超过2G就最好对其进行分区,对于大表创建分区的好处是显而易见的,这里不多论

why,而将重点放在when以及how

WHEN

一、When使用Range分区

Range分区呢是应用范围比较广的表分区方式,它是以列的值的范围来做为分区的划分条件,将记录存放

到列值所在的range分区中,比如按照时间划分,20081季度的数据放到a分区,082季度的数据放到b

分区,因此在创建的时候呢,需要你指定基于的列,以及分区的范围值,如果某些记录暂无法预测范围,可以

创建maxvalue分区,所有不在指定范围内的记录都会被存储到maxvalue所在分区中,并且支持指定多列做为

依赖列,后面在讲how的时候会详细谈到。

二、When使用Hash分区

通常呢,对于那些无法有效划分范围的表,可以使用hash分区,这样对于提高性能还是会有一定的帮助。

hash分区会将表中的数据平均分配到你指定的几个分区中,列所在分区是依据分区列的hash值自动分配,因此

你并不能控制也不知道哪条记录会被放到哪个分区中,hash分区也可以支持多个依赖列。

三、When使用List分区

List分区与range分区和hash分区都有类似之处,该分区与range分区类似的是也需要你指定列的值,但这

又不同与range分区的范围式列值---其分区值必须明确指定,也不同与hash分区---通过明确指定分区值,你能

控制记录存储在哪个分区。它的分区列只能有一个,而不能像range或者hash分区那样同时指定多个列做为分

区依赖列,不过呢,它的单个分区对应值可以是多个。

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

你在分区时必须确定分区列可能存在的值,一旦插入的列值不在分区范围内,则插入/更新就会失败,因此

通常建议使用list分区时,要创建一个default分区存储那些不在指定范围内的记录,类似range分区中的maxvalue

分区。

四、When使用组合分区

如果某表按照某列分区之后,仍然较大,或者是一些其它的需求,还可以通过分区内再建子分区的方式将

分区再分区,即组合分区的方式。

组合分区呢在10g中有两种:range-hashrange-list。注意顺序哟,根分区只能是range分区,子分区可以

hash分区或list分区。

提示:11g在组合分区功能这块有所增强,又推出了range-range,list-range,list-list,list-hash,这就相当于除

hash外三种分区方式的笛卡尔形式都有了。为什么会没有hash做为根分区的组合分区形式呢,再仔细回味一下

第二点,你一定能够想明白~~

HOW

一、如何创建

如果想对某个表做分区,必须在创建表时就指定分区,我们可以对一个包含分区的表中的分区做修改,但

不能直接将一个未分区的表修改成分区表(起码在10g是不行的,当然你可能会说,可以通过在线重定义的方式

但是这不是直接哟,这也是借助临时表间接实现的)

创建表或索引的语法就不说了,大家肯定比我还熟悉,而想在建表(索引)同时指定分区也非常容易,只需要

把创建分区的子句放到";"前就行啦,同时需要注意表的rowmovement属性,它用来控制是否允许修改列值所造

成的记录移动至其它分区存储,有enable|disable两种状态,默认是disablerowmovement,当disable时,如果

记录要被更新至其它分区,则更新语句会报错。

下面分别演示不同分区方式的表和索引的创建:

1、创建range分区

语法如下,图:[range_]

需要我们指定的有:

column:分区依赖列(如果是多个,以逗号分隔);

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

partition:分区名称;

valueslessthan:后跟分区范围值(如果依赖列有多个,范围对应值也应是多个,中间以逗号分隔);

tablespace_clause:分区的存储属性,例如所在表空间等属性(可为空),默认继承基表所在表空间的

属性。

创建一个标准的range分区表:

JSSWEB>createtablet_partition_range(idnumber,namevarchar2(50))

2partitionbyrange(id)(

3partitiont_range_p1valueslessthan(10)tablespacetbspart01,

4partitiont_range_p2valueslessthan(20)tablespacetbspart02,

5partitiont_range_p3valueslessthan(30)tablespacetbspart03,

6partitiont_range_pmaxvalueslessthan(maxvalue)tablespacetbspart04

7);

表已创建。

要查询创建分区的信息,可以通过查询user_part_tables,user_tab_partitions两个数据字典(索引分区、

组织分区等信息也有对应的数据字典,后续示例会逐步提及)

user_part_tables:记录分区的表的信息;

user_tab_partitions:记录表的分区的信息。

例如:

JSSWEB>selecttable_name,partitioning_type,partition_count

2Fromwheretable_name='T_PARTITION_RANGE';

user_part_tables

TABLE_NAMEPARTITIPARTITION_COUNT

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

T_PARTITION_RANGERANGE4

JSSWEB>selectpartition_name,high_value,tablespace_name

2fromuser_tab_partitionswheretable_name='T_PARTITION_RANGE'

3orderbypartition_position;

PARTITION_NAMEHIGH_VALUETABLESPACE_NAME

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

T_RANGE_P110TBSPART01

T_RANGE_P220TBSPART02

T_RANGE_P330TBSPART03

T_RANGE_PMAXMAXVALUETBSPART04

创建global索引range分区:

JSSWEB>createindexidx_parti_range_idont_partition_range(id)

2globalpartitionbyrange(id)(

3partitioni_range_p1valueslessthan(10)tablespacetbspart01,

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

4partitioni_range_p2valueslessthan(40)tablespacetbspart02,

5partitioni_range_pmaxvalueslessthan(maxvalue)tablespacetbspart03);

索引已创建。

由上例可以看出,创建global索引的分区与创建表的分区语句格式完全相同,而且其分区形式与索引

所在表的分区形式没有关联关系。

ge

注意:我们这里借助上面的表t_partition_range来演示创建range分区的global索引,并不表示ranrange

分区的表,只能创建range分区的global索引,只要你想,也可以为其创建hash分区的global索引。

查询索引的分区信息可以通过user_part_indexesuser_ind_partitions两个数据字典:

JSSWEB>selectindex_name,partitioning_type,partition_count

2Fromuser_part_indexes

3whereindex_name='IDX_PARTI_RANGE_ID';

INDEX_NAMEPARTITIPARTITION_COUNT

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

IDX_PARTI_RANGE_IDRANGE3

JSSWEB>selectpartition_name,high_value,tablespace_name

2fromuser_ind_partitions

3whereindex_name='IDX_PARTI_RANGE_ID'

4orderbypartition_position;

PARTITION_NAMEHIGH_VALUETABLESPACE_NAME

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

I_RANGE_P110TBSPART01

I_RANGE_P240TBSPART02

I_RANGE_PMAXMAXVALUETBSPART03

Local分区索引的创建最简单,例如:

仍然借助t_partition_range表来创建索引

--首先删除之前创建的global索引

JSSWEB>dropindexIDX_PARTI_RANGE_ID;

索引已删除。

JSSWEB>createindexIDX_PARTI_RANGE_IDonT_PARTITION_RANGE(id)local;

索引已创建。

查询相关数据字典:

JSSWEB>selectindex_name,partitioning_type,partition_count

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

2Fromuser_part_indexes

3whereindex_name='IDX_PARTI_RANGE_ID';

INDEX_NAMEPARTITIPARTITION_COUNT

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

IDX_PARTI_RANGE_IDRANGE4

JSSWEB>selectpartition_name,high_value,tablespace_name

2fromuser_ind_partitions

3whereindex_name='IDX_PARTI_RANGE_ID'

4orderbypartition_position;

PARTITION_NAMEHIGH_VALUETABLESPACE_NAME

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

T_RANGE_P110TBSPART01

T_RANGE_P220TBSPART02

T_RANGE_P330TBSPART03

T_RANGE_PMAXMAXVALUETBSPART04

可以看出,local索引的分区完全继承表的分区的属性,包括分区类型,分区的范围值即不需指定也不

能更改,这就是前面说的:local索引的分区维护完全依赖于其索引所在表。

不过呢分区名称,以及分区所在表空间等信息是可以自定义的,例如:

SQL>createindexIDX_PART_RANGE_IDONT_PARTITION_RANGE(id)local(

2partitioni_range_p1tablespacetbspart01,

3partitioni_range_p2tablespacetbspart01,

4partitioni_range_p3tablespacetbspart02,

5partitioni_range_pmaxtablespacetbspart02

6);

索引已创建。

SQL>selectindex_name,partitioning_type,partition_count

2Fromuser_part_indexes

3whereindex_name='IDX_PART_RANGE_ID';

INDEX_NAMEPARTITIPARTITION_COUNT

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

IDX_PART_RANGE_IDRANGE4

SQL>selectpartition_name,high_value,tablespace_name

2fromuser_ind_partitions

3whereindex_name='IDX_PART_RANGE_ID'

4orderbypartition_position;

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

PARTITION_NAMEHIGH_VALUETABLESPACE_NAME

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

I_RANGE_P110TBSPART01

I_RANGE_P220TBSPART01

I_RANGE_P330TBSPART02

I_RANGE_PMAXMAXVALUETBSPART02

2、创建hash分区

语法如下:[:hash_]

语法看起来比range复杂,其实使用起来比range更简单,这里需要我们指定的有:

column:分区依赖列(支持多个,中间以逗号分隔);

partition:指定分区,有两种方式:

直接指定分区名,分区所在表空间等信息

只指定分区数量,和可供使用的表空间。

创建hash分区表

JSSWEB>createtablet_partition_hash(idnumber,namevarchar2(50))

2partitionbyhash(id)(

3partitiont_hash_p1tablespacetbspart01,

4partitiont_hash_p2tablespacetbspart02,

5partitiont_hash_p3tablespacetbspart03);

表已创建。

要实现同样效果,你还可以这样:

JSSWEB>createtablet_partition_hash2(idnumber,namevarchar2(50))

2partitionbyhash(id)

3partitions3storein(tbspart01,tbspart02,tbspart03);

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

表已创建。

这就是上面说的,直接指定分区数量和可供使用的表空间。

提示:这里分区数量和可供使用的表空间数量之间没有直接对应关系。分区数并不一定要等于表

空间数。

要查询表的分区信息,仍然是通过user_part_tables,user_tab_partitions两个数据字典,这里不再举

例。

Global索引hash分区

Hash分区索引的子句与hash分区表的创建子句完全相同,例如:

JSSWEB>createindexidx_part_hash_idont_partition_hash(id)

2globalpartitionbyhash(id)

3partitions3storein(tbspart01,tbspart02,tbspart03);

索引已创建。

查询索引的分区信息也仍是通过user_part_indexesuser_ind_partitions两个数据字典,不再举例。

创建Local索引

在前面学习range分区时,我们已经对Local索引的特性做了非常清晰的概述,因此这里也不再举

例,如有疑问,建议再仔细复习range分区的相关示例,如果还有疑问,当面问我好了:)

综上:

对于global索引分区而言,在10g中只能支持range分区和hash分区,因此后续示例中不会再提

及。

对于local索引分区而言,其分区形式完全依赖于索引所在表的分区形式,不管从创建语法还是理

解难度均无技术含量,因此后续也不再提供示例。

注意,在创建索引时如果不显式指定globallocal,则默认是global

注意,在创建global索引时如果不显式指定分区子句,则默认不分区(废话)

3、创建list分区

创建语法如下:[图:list_]

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

需要我们指定的有:

column:分区依赖列,注意:只能是一个;

partition:分区名称;

literal:分区对应值,注意:每个分区可以对应多个值;

tablespace_clause:分区的存储属性,例如所在表空间等属性(可为空),默认继承基表所在表空间的

属性。

创建list分区表示例:

JSSWEB>createtablet_partition_list(idnumber,namevarchar2(50))

2partitionbylist(id)(

3partitiont_list_p1values(1,2,3,4,5,6,7,8,9)tablespacetbspart01,

4partitiont_list_p2values(10,11,12,13,14,15,16,17,18,19)tablespacetbspart02,

5partitiont_list_p3values(20,21,22,23,24,25,26,27,28,29)tablespacetbspart03,

6partitiont_list_pdvalues(default)tablespacetbspart04);

表已创建。

上例能够实现与前面range分区示例相同的效果,当然针对本示例而言,list分区显然不好用啊~~~

4、创建range-hash组合分区

语法如下:图[composite_]

需要我们指定的有:

column_list:分区依赖列(支持多个,中间以逗号分隔);

subpartition:子分区方式,有两处:

Subpartition_by_list:语法与list分区完全相同,只不过把关键字partition换成subpartition

Subpartition_by_hash:语法与hash分区完全相同,只不过把关键字partition换成subpartition

partition:分区名称;

range_partition_values_clause:range分区范围值的语法;

tablespace_clause:分区的存储属性,例如所在表空间等属性(可为空),默认继承基表所在表空间的

属性。

组合分区相对于普通分区,语法上稍稍复杂了一些,但也正因如此,其子分区的创建可以非常灵活,

下面分别举几个例子(注:仅示例,并非穷举所有形式)

为所有分区各创建4hash子分区

/QQ5454589君三思QQ群:59666289三思笔记]全面学习分区表及分区索引

JSSWEB>createtablet_partition_rh(idnumber,namevarchar2(50))

2partitionbyrange(id)subpartitionbyhash(name)

3subpartitions4storein(tbspart01,tbspart02,tbspart03,tbspart04)(

4partitiont_r_p1valueslessthan(10)tablespacetbspart01,

5partitiont_r_p2valueslessthan(20)tablespacetbspart02,

6partitiont_r_p3valueslessthan(30)tablespacetbspart03,

7partitiont_r_pdvalueslessthan(maxvalue)tablespacetbspart04);

表已创建。

JSSWEB>selectpartitioning_type,subpartitioning_type,partition_count,def_subpartition_count

2Fromuser_part_tableswheretable_name='T_PARTITION_RH';

PARTITISUBPARTPARTITION_COUNTDEF_SUBPARTITION_COUNT

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

RANGEHASH44

JSSWEB>selectpartition_name,subpartition_count,high_value

2fromuser_tab_partitionswheretable_name='T_PARTITION_RH';

PARTITION_NAMESUBPARTITION_COUNTHIGH_VALUE

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

T_R_P2420

T_R_P3430

T_R_PD4MAXVALUE

T_R_P1410

JSSWEB>selectpartition_name,subpartition_name,tablespace_name

2fromuser_tab_subpartitionswheretable_name='T_PARTITION_RH';

PARTITION_NAMESUBPARTITION_NAMETABLESPACE_NAME

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

T_R_P2SYS_SUBP140TBSPART02

T_R_P2SYS_SUBP139TBSPART02

T_R_P2SYS_SUBP138TBSPART02

T_R_P2SYS_SUBP137TBSPART02

T_R_P3SYS_SUBP144TBSPART03

T_R_P3SYS_SUBP143TBSPART03

T_R_P3SYS_SUBP142TBSPART03

T_R_P3SYS_SUBP141TBSPART03

T_R_PDSYS_SUBP148TBSPART04

T_R_PDSYS_SUBP147TBSPART04

T_R_PDSYS_SUBP146TBSPART04

T_R_PDSYS_SUBP145TBSPART04

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

T_R_P1SYS_SUBP133TBSPART01

T_R_P1SYS_SUBP136TBSPART01

T_R_P1SYS_SUBP135TBSPART01

T_R_P1SYS_SUBP134TBSPART01

已选择16行。

这里我们要学到一个新的数据字典:user_tab_subpartitions,用于查询表的子分区信息。

对某个分区创建hash子分区

JSSWEB>createtablet_partition_rh(idnumber,namevarchar2(50))

2partitionbyrange(id)subpartitionbyhash(name)(

3partitiont_r_p1valueslessthan(10)tablespacetbspart01,

4partitiont_r_p2valueslessthan(20)tablespacetbspart02,

5partitiont_r_p3valueslessthan(30)tablespacetbspart03

6(subpartitiont_r_p3_h1tablespacetbspart01,

7subpartitiont_r_p3_h2tablespacetbspart02,

8subpartitiont_r_p3_h3tablespacetbspart03),

9partitiont_r_pdvalueslessthan(maxvalue)tablespacetbspart04);

表已创建。

JSSWEB>selectpartitioning_type,subpartitioning_type,partition_count,def_subpartition_count

2Fromuser_part_tableswheretable_name='T_PARTITION_RH';

PARTITISUBPARTPARTITION_COUNTDEF_SUBPARTITION_COUNT

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

RANGEHASH41

JSSWEB>selectpartition_name,subpartition_count,high_value

2fromuser_tab_partitionswheretable_name='T_PARTITION_RH';

PARTITION_NAMESUBPARTITION_COUNTHIGH_VALUE

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

T_R_P1110

T_R_P2120

T_R_P3330

T_R_PD1MAXVALUE

JSSWEB>selectpartition_name,subpartition_name,tablespace_name

2fromuser_tab_subpartitionswheretable_name='T_PARTITION_RH';

PARTITION_NAMESUBPARTITION_NAMETABLESPACE_NAME

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

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

T_R_P1SYS_SUBP149TBSPART01

T_R_P2SYS_SUBP150TBSPART02

T_R_P3T_R_P3_H3TBSPART03

T_R_P3T_R_P3_H2TBSPART02

T_R_P3T_R_P3_H1TBSPART01

T_R_PDSYS_SUBP151TBSPART04

已选择6行。

当然,还可以给各个分区指定不同的子分区

JSSWEB>createtablet_partition_rh(idnumber,namevarchar2(50))

2partitionbyrange(id)subpartitionbyhash(name)(

3partitiont_r_p1valueslessthan(10)tablespacetbspart01,

4partitiont_r_p2valueslessthan(20)tablespacetbspart02

5(subpartitiont_r_p2_h1tablespacetbspart01,

6subpartitiont_r_p2_h2tablespacetbspart02),

7partitiont_r_p3valueslessthan(30)tablespacetbspart03

8subpartitions3storein(tbspart01,tbspart02,tbspart03),

9partitiont_r_pdvalueslessthan(maxvalue)tablespacetbspart04

10(subpartitiont_r_p3_h1tablespacetbspart01,

11subpartitiont_r_p3_h2tablespacetbspart02,

12subpartitiont_r_p3_h3tablespacetbspart03)

13);

表已创建。

JSSWEB>selectpartitioning_type,subpartitioning_type,partition_count,def_subpartition_count

2Fromuser_part_tableswheretable_name='T_PARTITION_RH';

PARTITISUBPARTPARTITION_COUNTDEF_SUBPARTITION_COUNT

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

RANGEHASH41

JSSWEB>selectpartition_name,subpartition_count,high_value

2fromuser_tab_partitionswheretable_name='T_PARTITION_RH';

PARTITION_NAMESUBPARTITION_COUNTHIGH_VALUE

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

T_R_P1110

T_R_P2220

T_R_P3330

T_R_PD3MAXVALUE

JSSWEB>selectpartition_name,subpartition_name,tablespace_name

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

2fromuser_tab_subpartitionswheretable_name='T_PARTITION_RH';

PARTITION_NAMESUBPARTITION_NAMETABLESPACE_NAME

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

T_R_P1SYS_SUBP152TBSPART01

T_R_P2T_R_P2_H2TBSPART02

T_R_P2T_R_P2_H1TBSPART01

T_R_P3SYS_SUBP155TBSPART03

T_R_P3SYS_SUBP154TBSPART02

T_R_P3SYS_SUBP153TBSPART01

T_R_PDT_R_P3_H3TBSPART03

T_R_PDT_R_P3_H2TBSPART02

T_R_PDT_R_P3_H1TBSPART01

已选择9行。

提示:由上两例可以看出,未显式指定子分区的分区,系统会自动创建一个子分区。

分区模板的应用

oracle还提供了一种称为分区模板的功能,在指定子分区信赖列之后,制订子分区的存储模板,各个

分区即会按照子分区模式创建子分区,例如:

JSSWEB>createtablet_partition_rh(idnumber,namevarchar2(50))

2partitionbyrange(id)subpartitionbyhash(name)

3subpartitiontemplate(

4subpartitionh1tablespacetbspart01,

5subpartitionh2tablespacetbspart02,

6subpartitionh3tablespacetbspart03,

7subpartitionh4tablespacetbspart04)(

8partitiont_r_p1valueslessthan(10)tablespacetbspart01,

9partitiont_r_p2valueslessthan(20)tablespacetbspart02,

10partitiont_r_p3valueslessthan(30)tablespacetbspart03,

11partitiont_r_pdvalueslessthan(maxvalue)tablespacetbspart04);

表已创建。

JSSWEB>selectpartition_name,subpartition_name,tablespace_name

2fromuser_tab_subpartitionswheretable_name='T_PARTITION_RH';

PARTITION_NAMESUBPARTITION_NAMETABLESPACE_NAME

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

T_R_P1T_R_P1_H4TBSPART01

T_R_P1T_R_P1_H3TBSPART01

T_R_P1T_R_P1_H2TBSPART01

T_R_P1T_R_P1_H1TBSPART01

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

T_R_P2T_R_P2_H4TBSPART02

T_R_P2T_R_P2_H3TBSPART02

T_R_P2T_R_P2_H2TBSPART02

T_R_P2T_R_P2_H1TBSPART02

T_R_P3T_R_P3_H4TBSPART03

T_R_P3T_R_P3_H3TBSPART03

T_R_P3T_R_P3_H2TBSPART03

T_R_P3T_R_P3_H1TBSPART03

T_R_PDT_R_PD_H4TBSPART04

T_R_PDT_R_PD_H3TBSPART04

T_R_PDT_R_PD_H2TBSPART04

T_R_PDT_R_PD_H1TBSPART04

已选择16行。

5、创建range-list组合分区

Range-list组合分区的创建与range-hash极为相似,只是子分区为list分区,当然同样也可以应用分区

模板,下面也举一个示例:

JSSWEB>createtablet_partition_rl(idnumber,namevarchar2(50))

2partitionbyrange(id)subpartitionbylist(name)

3subpartitiontemplate(

4subpartitionl1values('aa')tablespacetbspart01,

5subpartitionl2values('bb')tablespacetbspart02,

6subpartitionl3values('cc')tablespacetbspart03,

7subpartitionl4values('dd')tablespacetbspart04)(

8partitiont_r_p1valueslessthan(10)tablespacetbspart01,

9partitiont_r_p2valueslessthan(20)tablespacetbspart02,

10partitiont_r_p3valueslessthan(30)tablespacetbspart03,

11partitiont_r_pdvalueslessthan(maxvalue)tablespacetbspart04);

表已创建。

JSSWEB>selectpartition_name,subpartition_name,tablespace_name

2fromuser_tab_subpartitionswheretable_name='T_PARTITION_RL';

PARTITION_NAMESUBPARTITION_NAMETABLESPACE_NAME

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

T_R_P1T_R_P1_L4TBSPART01

T_R_P1T_R_P1_L3TBSPART01

T_R_P1T_R_P1_L2TBSPART01

T_R_P1T_R_P1_L1TBSPART01

T_R_P2T_R_P2_L4TBSPART02

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

T_R_P2T_R_P2_L3TBSPART02

T_R_P2T_R_P2_L2TBSPART02

T_R_P2T_R_P2_L1TBSPART02

T_R_P3T_R_P3_L4TBSPART03

T_R_P3T_R_P3_L3TBSPART03

T_R_P3T_R_P3_L2TBSPART03

T_R_P3T_R_P3_L1TBSPART03

T_R_PDT_R_PD_L4TBSPART04

T_R_PDT_R_PD_L3TBSPART04

T_R_PDT_R_PD_L2TBSPART04

T_R_PDT_R_PD_L1TBSPART04

已选择16行。

其它方式的创建对于range-list同样好使,这里不再举例,如有不明,请自学复习前章range_hash组合

分区。

对于复合分区的local索引,我们也举一个示例,查看其分区情况:

SQL>createindexidx_part_rl_idont_partition_rl(id)local;

索引已创建。

又可以学几个数据字典:user_part_indexesuser_ind_partitions前面已经认识了,user_ind_subpartitions

用来查询索引的子分区信息。

SQL>selecttable_name,partitioning_type,

2partition_count,def_subpartition_count

3fromuser_part_indexes

4whereindex_name='IDX_PART_RL_ID';

TABLE_NAMEPARTITIPARTITION_COUNTDEF_SUBPARTITION_COUNT

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

T_PARTITION_RLRANGE44

SQL>selectpartition_name,subpartition_count,high_value

2fromuser_ind_partitions

3whereindex_name='IDX_PART_RL_ID';

PARTITION_NAMESUBPARTITION_COUNTHIGH_VALUE

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

T_R_P1410

T_R_P2420

T_R_P3430

T_R_PD4MAXVALUE

SQL>selectpartition_name,subpartition_name,high_value,tablespace_name

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

2fromuser_ind_subpartitions

3whereindex_name='IDX_PART_RL_ID';

PARTITION_NAMESUBPARTITION_NAMEHIGH_VALUE

TABLESPACE_NAME

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

T_R_P1T_R_P1_L1'aa'TBSPART01

T_R_P1T_R_P1_L2'bb'TBSPART01

T_R_P1T_R_P1_L3'cc'TBSPART01

T_R_P1T_R_P1_L4'dd'TBSPART01

T_R_P2T_R_P2_L1'aa'TBSPART02

T_R_P2T_R_P2_L2'bb'TBSPART02

T_R_P2T_R_P2_L3'cc'TBSPART02

T_R_P2T_R_P2_L4'dd'TBSPART02

T_R_P3T_R_P3_L1'aa'TBSPART03

T_R_P3T_R_P3_L2'bb'TBSPART03

T_R_P3T_R_P3_L3'cc'TBSPART03

T_R_P3T_R_P3_L4'dd'TBSPART03

T_R_PDT_R_PD_L1'aa'TBSPART04

T_R_PDT_R_PD_L2'bb'TBSPART04

T_R_PDT_R_PD_L3'cc'TBSPART04

T_R_PDT_R_PD_L4'dd'TBSPART04

已选择16行。

还是与表的分区格式一样,不管是普通分区还是复合分区,local索引都没啥自主权啊。

6、公共准则

1、如果选择的分区不能确保各分区内记录量的基本平均,则这种分区方式有可能是不恰当的。

比如对于range分区,假设分了10个分区,而其中一个分区中的记录数占总记录数的90%,其它9

分区只占总记录数的10%,则这个分区方式就起不到数据平衡的作用。当然,如果你的目的并不是为了平

衡,只是为了区分数据,ok,对于这种情况,我想说的是,你务必要意识到存在这个问题。

2、对于分区的表或索引,其所涉及的所有分区,其块大小必须一致。

最后,建议对于上面创建的表或建表脚本妥善保存并记忆,后面我们需要频繁用到,后续示例将均主要依

赖前文中创建的表进行:)

二、如何管理

对于分区的表的操作很多,其中某些操作仅针对某些分区有效,为了避免在演示过程中浪费过多口水标注

哪些操作适用于哪些分区,咱们先在这儿列个表,哪个操作适用于哪种分区格式具体可以先参考下面这个表格:

分区表RangeListHashRange-HashRange-List是否带来IO操作

QQ群:59666289三思笔记]全面学习分区表及分区索引/QQ5454589君三思

增加分区支持支持支持支持支持hash类型外,均

(addpartition)不变带来大量IO

收缩分区//支持分区://

(coalescepartitions)子分区:支持

删除分区支持支持/分区:支持支持

(droppartition)子分区:/

交换分区支持支持支持支持支持

(exchangepartition)

合并分区支持支持/分区:支持支持

(mergepartition)子分区:/

修改默认属性支持支持支持支持支持

(modifydefaultattributes)

修改分区当前属性支持支持支持支持支持

(modifypartition)

List分区增加值/支持//分区:/

(modifypartitionaddvalues)子分区:支持

List分区删除值/支持//分区:/单纯删除操作无

(modifypartitiondropvalues)子分区:支持但可

成功删除,之前的

准备

一定量的IO

修改子分区模板///支持支持

移动分区支持支持支持分区:支持分区:支持

重命名分区支持支持支持支持支持

拆分分区支持支持/分区:支持支持

截断分区支持支持支持支持支持

(setsubpartitiontemplate)

(movepartition)子分区:/子分区:/

(renamepartition)

(splitpartition)子分区:/

(truncatepartition)

注:上述IO列的评估建立在假设分区中均存在一定量数据,并忽略修改数据字典可能触发的IO,忽略造

成的索引的重编译带来的IO

分区索引的操作也有一张表黑黑,如下:

分区索引索引类型RangeListHash组合分区是否带来IO操作

增加分区全局//支持/

(addpartition)

(droppartition)

(modifydefaultattributes)

修改分区当前属性全局支持///

本地////

全局支持///

本地////

全局支持///

本地支持支持支持支持

QQ5454589君三思QQ群:59666289三思笔记]全面学习分区表及分区索引/

(modifypartition)本地支持支持支持支持

重编译分区全局支持///

(rebuildpartition)

重命名分区全局支持///

(renamepartition)

拆分分区全局支持///

(splitpartition)

本地支持支持支持支持

本地支持支持支持支持

本地////

另外local索引前头我们多次提到了,其维护会在oracle操作表分区的时候自动进行,需要注意的是global

索引,当global索引所在表执行altertable涉及下列操作时,会导至该索引失效:

ADDPARTITION|SUBPARTITION

COALESCEPARTITION|SUBPARTITION

DROPPARTITION|SUBPARTITION

EXCHANGEPARTITION|SUBPARTITION

MERGEPARTITION|SUBPARTITION

MOVEPARTITION|SUBPARTITION

SPLITPARTITION|SUBPARTITION

TRUNCATEPARTITION|SUBPARTITION

因此,建议用户在执行上述操作sql语句后附加updateindexes子句,oracle即会自动维护全局索引,当然,

需要注意这中间有一个平衡,你要平衡操作ddl的时间和重建索引哪个时间更少,以决定是否需要附加update

indexes子句。

分区表的管理

1、增加表分区(addpartition)

增加表分区适应于所有的分区形式,其语法是altertabletbnameaddpartition.....

但是,需要注意对于像list,range这种存在范围值的分区,所要增加的分区值必须要大于当前分区中的

最大值(如果当前存在maxvaluedefault的分区,addpartition会报错,这种情况只能使用split,后面会

到)hash分区则无此限制。

例如:

JSSWEB>createtablet_partition_range(idnumber,namevarchar2(50))

2partitionbyrange(id)(

3partitiont_range_p1valueslessthan(10)tablespacetbspart01,

4partitiont_range_p2valueslessthan(20)tablespacetbspart02,

5partitiont_range_p3valueslessthan(30)tablespacetbspart03

6);

表已创建。

JSSWEB>altertablet_partition_range

2addpartitiont_range_p4valueslessthan(40);

表已更改。

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

Hashlist的语法与上类似,这里不再举例。

注意:

1、对于hash分区,当你执行addpartition操作的时候,oracle会自动选择一个分区,并重新分配部分

记录到新建的分区,这也意味着有可能带来一些IO操作。

2、执行altertable时未指定updateindexes子句:

如果是range/list分区,其local索引和global索引不会受影响;

如果是hash分区,新加分区及有数据移动的分区的local索引和glocal索引会被置为unuseable

需要重新编译。

3、复合分区完全适用上述所述规则。

2、收缩表分区(coalescepartitions)

Coalescepartition是个很有意思的分区功能,仅能被应用于hash分区或复合分区的hash子分区,执行

之后,会自动收缩当前的表分区,比如某表当前有5hash分区,执行altertabletbnamecoalescepartitions

后就变成4个,再执行一次就变成3个,再执行一次就变2个,再执行一次就...........就报错了:,对于已

分区的表至少要有一个分区存在的嘛!

例如:

JSSWEB>selecttable_name,partition_namefromuser_tab_partitions

2wheretable_name='T_PARTITION_HASH';

TABLE_NAMEPARTITION_NAME

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

T_PARTITION_HASHT_HASH_P2

T_PARTITION_HASHT_HASH_P3

T_PARTITION_HASHT_HASH_P4

T_PARTITION_HASHT_HASH_P5

T_PARTITION_HASHT_HASH_P1

JSSWEB>altertablet_partition_hashcoalescepartition;

表已更改。

JSSWEB>selecttable_name,partition_namefromuser_tab_partitions

2wheretable_name='T_PARTITION_HASH';

TABLE_NAMEPARTITION_NAME

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

T_PARTITION_HASHT_HASH_P2

T_PARTITION_HASHT_HASH_P3

T_PARTITION_HASHT_HASH_P4

T_PARTITION_HASHT_HASH_P1

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

注意,收缩的只是分区,并不会影响到数据,但是视被收缩分区中数据的多少,收缩表分区也会涉及

IO操作。

另外如果你在执行该语句时没有指定updateindexes子句,收缩过程中有数据改动的分区其local索引

glocal索引都会失效,需要重新编译。

3、删除表分区(droppartition)

删除表分区包含两种操作,分别是:

删除分区:altertable[tbname]droppartition[ptname];

删除子分区:altertable[tbname]dropsubpartition[ptname];

hash分区和hash子分区外,其它的分区格式都可以支持这项操作。

例如,删除分区:

JSSWEB>selecttable_name,partition_name

2fromuser_tab_partitionswheretable_name='T_PARTITION_LIST';

TABLE_NAMEPARTITION_NAME

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

T_PARTITION_LISTT_LIST_P1

T_PARTITION_LISTT_LIST_P2

T_PARTITION_LISTT_LIST_P3

T_PARTITION_LISTT_LIST_PD

JSSWEB>altertablet_partition_listdroppartitiont_list_p2;

表已更改。

提示,droppartition时,该分区内存储的数据也将同时删除,例如:

JSSWEB>insertintot_partition_listvalues(1,'a');

..........

--插入一批记录,分布于当前各个分区

..........

JSSWEB>commit;

提交完成。

JSSWEB>select*fromt_partition_list;

IDNAME

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

1a

2b

21a

22b

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

--单独查询t_list_p3分区,当前有数据

JSSWEB>select*fromt_partition_listpartition(t_list_p3);

IDNAME

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

21a

22b

--删除t_list_p3分区,数据会被同时删除

JSSWEB>altertablet_partition_listdroppartitiont_list_p3;

表已更改。

JSSWEB>select*fromt_partition_listpartition(t_list_p3);

select*fromt_partition_listpartition(t_list_p3)

*

1行出现错误:

ORA-02149:指定的分区不存在

JSSWEB>select*fromt_partition_list;

IDNAME

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

1a

2b

由于是ddl操作,这种删除也会是非常迅速的,因此如果你确认某个分区的数据都要被删除,使用drop

partition会比delete更加高效。如果你的本意是希望删除掉指定的分区但保留数据,你应该使用merge

partition,后面也会讲到。

同样,如果你在执行该语句时没有指定updateindexes子句,也会导致glocal索引的失效,至于local

索引嘛,删除分区时对应的索引分区会被同时删除,但其它分区的local索引不会受到影响。

4、交换表分区(ExchangePartitions)

直白的说就是迁移数据。迁移数据的方式很多,为什么要使用exchangepartition的方式呢,表急,听

三思慢慢道来。

Exchangepartition提供了一种方式,让你在表与表或分区与分区之间迁移数据,注意不是将表转换成

分区或非分区的形式,而仅只是迁移表中数据(互相迁移)由于其号称是采用了更改数据字典的方式,因此

效率最高(几乎不涉及io操作)Exchangepartition适用于所有分区格式,你可以将数据从分区表迁移到非

分区表,也可以从非分区表迁移至分区表,或者从hashpartitionrangepartition诸如此类吧。

其语法很简单:altertabletbname1exchangepartition/subpartitionptnamewithtabletbname2;

Exchangepartition迁移的方式也很有意思,言语表达怕大家听不明白,下面直接通过示例来表达:

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

借用前文中创建的空分区表:t_partition_range,并插入几条记录

JSSWEB>createtablet_partition_range(idnumber,namevarchar2(50))

2partitionbyrange(id)(

3partitiont_range_p1valueslessthan(10)tablespacetbspart01,

4partitiont_range_p2valueslessthan(20)tablespacetbspart02,

5partitiont_range_p3valueslessthan(30)tablespacetbspart03,

6partitiont_range_pmaxvalueslessthan(maxvalue)tablespacetbspart04

7);

表已创建。

JSSWEB>insertintot_partition_rangevalues(11,'a');

已创建1行。

JSSWEB>insertintot_partition_rangevalues(12,'b');

已创建1行。

JSSWEB>insertintot_partition_rangevalues(13,'c');

已创建1行。

JSSWEB>commit;

提交完成。

再创建一个非分区表,结构与t_partition_range相同

JSSWEB>createtablet_partition_range_tmp(idnumber,namevarchar2(50));

表已创建。

执行交换分区(我们知道刚插入到range分区表的数据都在分区t_range_p2中,因此这里指定交换该分

)

JSSWEB>altertablet_partition_rangeexchangepartitiont_range_p2

2withtablet_partition_range_tmp;

表已更改。

看看效果如何:

JSSWEB>select*fromt_partition_rangepartition(t_range_p2);

未选定行

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

JSSWEB>select*fromt_partition_range_tmp;

IDNAME

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

11a

12b

13c

记录成功交换到未分区的表中。

我们再执行一次exchangepartition的命令,看看又会发生什么呢

JSSWEB>select*fromt_partition_rangepartition(t_range_p2);

IDNAME

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

11a

12b

13c

JSSWEB>select*fromt_partition_range_tmp;

未选定行

又交换回来了,有点儿意思。

再做个更加明确的测试,我们往未分区的表中加入一些记录后再执行exchangepartition看看会发生什

么呢:

JSSWEB>insertintot_partition_range_tmpvalues(15,'d');

已创建1行。

JSSWEB>insertintot_partition_range_tmpvalues(16,'e');

已创建1行。

JSSWEB>insertintot_partition_range_tmpvalues(17,'d');

已创建1行。

JSSWEB>altertablet_partition_rangeexchangepartitiont_range_p2

2withtablet_partition_range_tmp;

表已更改。

JSSWEB>select*fromt_partition_rangepartition(t_range_p2);

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

IDNAME

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

15d

16e

17d

JSSWEB>select*fromt_partition_range_tmp;

IDNAME

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

11a

12b

13c

这就是前面所说的,互相交换的意思~~

注意:

涉及交换的两表之间表结构必须一致,除非附加withvalidation子句;

如果是从非分区表向分区表做交换,非分区表中的数据必须符合分区表中指定分区的规则,除非

附加withoutvalidation子句;

如果从分区表向分区表做交换,被交换的分区的数据必须符合分区规则,除非附加without

validation子句;

Global索引或涉及到数据改动了的global索引分区会被置为unusable,除非附加updateindexes

句。

提示:

一旦附加了withoutvalidation子句,则表示不再验证数据有效性,因此指定该子句时务必慎重。

例如:

JSSWEB>insertintot_partition_range_tmpvalues(8,'g');

已创建1行。

JSSWEB>altertablet_partition_rangeexchangepartitiont_range_p2

2withtablet_partition_range_tmpwithoutvalidation;

表已更改。

JSSWEB>select*fromt_partition_rangepartition(t_range_p2);

IDNAME

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

11a

12b

13c

8g

虽然新插入的记录并不符合t_range_p2分区的范围值,但指定了withoutvalidation后,数据仍然转换

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

成功。

5、合并表分区(MergePartitions)

合并两个分区成一个,适用于除hash之外的其它所有分区形式(hash分区有coalescepartition的嘛,前

头刚刚讲过)

语法很简单:altertabletbnamemergepartitions/subpartitionspt1,pt2intopartition/subpartitionpt3;

同样也支持updateindexes子句以避免单独执行造成索引失效的问题。

需要注意一点,要合并的两个分区必须是连续的,这点是由分区本身的特性所决定的,如例:

JSSWEB>altertablet_partition_rangemergepartitionst_range_p1,t_range_p2

2intopartitiont_range_pnew;

表已更改。

JSSWEB>selecttable_name,partition_name,high_valuefromuser_tab_partitions

2wheretable_name='T_PARTITION_RANGE';

TABLE_NAMEPARTITION_NAMEHIGH_VALUE

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

T_PARTITION_RANGET_RANGE_P330

T_PARTITION_RANGET_RANGE_PMAXMAXVALUE

T_PARTITION_RANGET_RANGE_PNEW20

JSSWEB>select*fromt_partition_rangepartition(t_range_pnew);

IDNAME

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

11a

12b

13c

8g

可见,合并分区操作不会造成数据丢失,另外如果你想为新分区指定属性的话,在语句末尾处增加存

储属性即可(如果不指定,则新分区默认继续表的存储属性)。例如:

JSSWEB>selectpartition_name,high_value,tablespace_namefromuser_tab_partitions

2wheretable_name='T_PARTITION_LIST';

PARTITION_NAMEHIGH_VALUETABLESPACE_NAME

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

T_LIST_P11,2,3,4,5,6,7,8,9,10TBSPART01

T_LIST_P211,12,13,14,15,16,17,18,19,20TBSPART02

T_LIST_P321,22,23,24,25,26,27,28,29,30TBSPART03

T_LIST_PDdefaultTBSPART04

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

JSSWEB>altertablet_partition_listmergepartitionst_list_p2,t_list_p3

2intopartitiont_list_p2tablespacetbspart02;

表已更改。

JSSWEB>selectpartition_name,high_value,tablespace_namefromuser_tab_partitions

2wheretable_name='T_PARTITION_LIST';

HIGH_VALUETABLESPACE_NAMEPARTITION_NAME

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

1,2,3,4,5,6,7,8,9,10TBSPART01T_LIST_P1

21,22,23,24,25,26,27,28,29,30,11,12,13TBSPART02T_LIST_P2

,14,15,16,17,18,19,20

T_LIST_PDdefaultTBSPART04

注意,merge分区操作与coalesce分区操作一样,视被合并的分区数据量多少,都可能涉及到大量的

IO操作。

其它合并组合分区的操作与上类似,如果要合并组合分区,注意关键字是mergesubpartitions,这里就

不做演示了。

6list--AddValues

、修改表分区

从标题即可得知,此命令仅应用于list分区或list子分区,语法也非常简单:

Altertabletbnamemodifypartition/subpartitionptnameaddvalues(vn);

举个例子:

JSSWEB>selectpartition_name,high_valuefromuser_tab_partitions

2wheretable_name='T_PARTITION_LIST';

PARTITION_NAMEHIGH_VALUE

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

T_LIST_P11,2,3,4,5,6,7,8,9,10

T_LIST_P221,22,23,24,25,26,27,28,29,30,11,12,13

,14,15,16,17,18,19,20

T_LIST_PDdefault

JSSWEB>altertablet_partition_listmodifypartitiont_list_p1addvalues(31,33);

表已更改。

JSSWEB>selectpartition_name,high_valuefromuser_tab_partitions

2wheretable_name='T_PARTITION_LIST';

PARTITION_NAMEHIGH_VALUE

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

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

T_LIST_P11,2,3,4,5,6,7,8,9,10,31,33

T_LIST_P221,22,23,24,25,26,27,28,29,30,11,12,13

,14,15,16,17,18,19,20

T_LIST_PDdefault

唯一的限制是注意要添加的新value值不能存在于当前任何分区中,并且当前表也不能存在记录值为新

值的记录,特别是当你创建了default分区的时候,有必要先检查一下当前表不存在要添加的值,不然命令

执行会出错,例如:

JSSWEB>insertintot_partition_listvalues(32,'a');

已创建1行。

JSSWEB>altertablet_partition_listmodifypartitiont_list_p1addvalues(32);

altertablet_partition_listmodifypartitiont_list_p1addvalues(32)

*

1行出现错误:

ORA-14324:所要添加的值已存在于DEFAULT分区之中

提示,增加新的列表值不会影响到表中原有的记录,因此不会对索引造成影响。

7list--DropValues

、修改表分区

与上类似,也是只能应用于list分区,不过功能相反,该命令是用来删除指定分区的value值,语法如

下:

Altertabletbnamemodifypartition/subpartitionptnamedropvalues(vn);

同样在删除list分区value列值的时候,也必须确认当前分区存在指定的value值,但是没有任何应用

该值的记录,有点儿饶是吧,脑袋多转几圈就好了。

举个例子:

JSSWEB>altertablet_partition_listmodifypartitiont_list_p1dropvalues(31);

表已更改。

成功执行了是吧,接着来看

JSSWEB>altertablet_partition_listmodifypartitiont_list_p1dropvalues(31);

altertablet_partition_listmodifypartitiont_list_p1dropvalues(31)

*

1行出现错误:

ORA-14313:31不在分区T_LIST_P1

出错了吧,这是其中的一种错误情形,即前面说的,要确保当前分区中存在指定的value值,再往下看

JSSWEB>altertablet_partition_listmodifypartitiont_list_p1addvalues(31);

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

表已更改。

JSSWEB>insertintot_partition_listvalues(31,'b');

已创建1行。

JSSWEB>altertablet_partition_listmodifypartitiont_list_p1dropvalues(31);

altertablet_partition_listmodifypartitiont_list_p1dropvalues(31)

*

1行出现错误:

ORA-14518:分区包含的某些行对应于已删除的值

这是另外的一种错误情形,即要确保拆分分区的记录中,没有应用了指定value值的记录。

8、拆分表分区(SplitPartition)

如果你对我们前面讲到过的mergepartition还有印象的话,那么学习Splitpartition也不会遇到什么障碍

splitpartition的功能与mergepartition功能正好相反:后者是将两个全区合并成一个,前者则是将一个分区

拆分成两个。其用途非常广泛,比如通常见你发现某个分区过大,你就可以通过这种方式将该分区分解成

多个小分区,对我而言最常用到的,当然还是splitmaxvalue/default的分区。

该命令的语法针对不同分区会有不同的形式,

Forrangepartitionaltertabletbnamesplitpartitionptnameat(value)into(partitionnewpt1

tbs_clause,partitionnewpt2tbs_clause);

Forlistpartition:altertabletbnamesplitpartitionptnamevalues(vn)into(partitionnewpt1

tbs_clause,partitionnewpt2tbs_clause);

上述两项,如果是操作子分区,则将partition关键字换成subpartition即可。旧分区中符合新定义值的

记录会存储到指定的第一个分区中,其它的记录存储到第二个分区。

例如,range分区的示例:

JSSWEB>selectpartition_name,high_value,tablespace_namefromuser_tab_partitions

2wheretable_name='T_PARTITION_RANGE';

PARTITION_NAMEHIGH_VALUETABLESPACE_NAME

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

T_RANGE_P330TBSPART03

T_RANGE_PMAXMAXVALUETBSPART04

T_RANGE_P120TBSPART02

我们将t_range_p1分区分隔到两个分区中,小于10的存放新建分区t_range_p1(已非原t_range_p1

只是名称相同而已),其它数据存入t_range_p2分区:

>

altertablet_partition_rangesplitpartitiont_range_p1at(10)intoJSSWEB>JSSWEB

2(partitiont_range_p1tablespacetbspart01,

3partitiont_range_p2tablespacetbspart02);

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

表已更改。

JSSWEB>selectpartition_name,high_value,tablespace_namefromuser_tab_partitions

2wheretable_name='T_PARTITION_RANGE';

PARTITION_NAMEHIGH_VALUETABLESPACE_NAME

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

T_RANGE_P330TBSPART03

T_RANGE_PMAXMAXVALUETBSPART04

T_RANGE_P110TBSPART01

T_RANGE_P220TBSPART02

再来演示一个list分区的例子:

JSSWEB>selectpartition_name,high_value,tablespace_namefromuser_tab_partitions

2wheretable_name='T_PARTITION_LIST';

PARTITION_NAMEHIGH_VALUETABLESPACE_NAME

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

T_LIST_P11,2,3,4,5,6,7,8,9,10,33TBSPART01

T_LIST_P221,22,23,24,25,26,27,28,29,30,TBSPART02

11,12,13,14,15,16,17,18,19,20

T_LIST_PDdefaultTBSPART04

我们将t_list_p2分区中分区值是2打头的存储到t_list_p3分区中,其它值存储到t_list_p2分区:

JSSWEB>altertablet_partition_listsplitpartitiont_list_p2values

2(20,21,22,23,24,25,26,27,28,29)into

3(partitiont_list_p3tablespacetbspart03,

4partitiont_list_p2);

表已更改。

JSSWEB>selectpartition_name,high_value,tablespace_namefromuser_tab_partitions

2wheretable_name='T_PARTITION_LIST';

PARTITION_NAMEHIGH_VALUETABLESPACE_NAME

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

T_LIST_P11,2,3,4,5,6,7,8,9,10,33TBSPART01

T_LIST_P230,11,12,13,14,15,16,17,18,19TBSPART02

T_LIST_PDdefaultTBSPART04

T_LIST_P320,21,22,23,24,25,26,27,28,29TBSPART03

提示:

直接用addpartition就好了)splitpartition/subpartition不能用于hash分区或hash子分区(hash的话,

可能需要花费不小的代价,相当于该分区数splitpartition/subpartition视被分隔的分区数据量多少,

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

据的全扫描,我们也许可以形容为:fullpartitionscan:),除非:

Split后的两个分区中,至少有一个是空的,并且非空的那个分区的存储属性与split前的存储

属性完全相同

如果split的分区包含lob字段,split后非空的那个分区中该字段的存储属性也必须与split

的存储属性完全相同。

这种情况下的splitpartition/subpartition也会非常高效,oracle会自动进行优化,此时的分区操作类

似于addpartition

通常情况下,如果在执行splitpartition/subpartition时,如果没有指定updateindexes子句,都会造

localglobal索引的失效。注意,我们说的是通常,如果你splitpartition/subpartition的是个空分区,或

者没有触发任何数据移动或变化,那么即使不加updateindexes,也不会影响到索引。当然,保险起见,建

议你还是执行完之后,查询一下数据字典,确认一下当前索引的状态。

9、截断表分区(TruncatePartition)

Truncatepartition就像truncatetable一样,直接从头部截断数据,用来删除数据那是效率超高无比。但

是如果该表有外键引用的话,ddltruncate就不好使了,这时候你只能要么使用delete,要么先disable

外键关联再truncate了。同样,在不指定updateindexes子句的情况下,truncatepartition也会造成分区所在

表的global索引失效。

语法非常简单:altertabletbnametruncatepartition/subpartitionptname;

例如:

JSSWEB>select*fromt_partition_rangepartition(t_range_p1);

IDNAME

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

11a

12b

13c

JSSWEB>altertablet_partition_rangetruncatepartitiont_range_p1;

表被截断。

JSSWEB>select*fromt_partition_rangepartition(t_range_p1);

未选定行

10、移动表分区(MovePartition)

Movepartitionmodifypartition的功能相似,但又比之更加强劲,比如可以修改分区所在表空间等等

movetable的操作很类似,某些时间也非常有用,比如降低行迁移。语法很简单:

Altertabletbnamemovepartition/subpartition;

例如:

JSSWEB>selectpartition_name,tablespace_namefromuser_tab_partitions

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

2wheretable_name='T_PARTITION_RANGE';

PARTITION_NAMETABLESPACE_NAME

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

T_RANGE_P3TBSPART03

T_RANGE_PMAXTBSPART04

T_RANGE_P1WEBTBS

JSSWEB>altertablet_partition_rangemovepartitiont_range_p1tablespacetbspart02;

表已更改。

JSSWEB>selectpartition_name,tablespace_namefromuser_tab_partitions

2wheretable_name='T_PARTITION_RANGE';

PARTITION_NAMETABLESPACE_NAME

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

T_RANGE_P3TBSPART03

T_RANGE_PMAXTBSPART04

T_RANGE_P1TBSPART02

提示:movepartition/subpartiton时会锁表,并且movepartition/subpartiton视被移动分区中数据量的多

少,会带来相应的IO操作。同时还需要注意,如果在movepartition/subpartiton时没有指定updateindexes

子句,则被移动分区所在的local索引以及全局索引都会失效,需要手工rebuilding

11、重命名表分区(RenamePartition)

就是改名,跟改表名、改列名的操作目的是类似的,语法也很简单:

Altertabletbnamerenamepartitionptnametonewptname;

举个例子:

JSSWEB>selectpartition_namefromuser_tab_partitionswheretable_name='T_PARTITION_RANGE';

PARTITION_NAME

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

T_RANGE_P3

T_RANGE_PMAX

T_RANGE_PNEW

JSSWEB>altertablet_partition_rangerenamepartitiont_range_pnewtot_range_p1;

表已更改。

JSSWEB>selectpartition_namefromuser_tab_partitionswheretable_name='T_PARTITION_RANGE';

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

PARTITION_NAME

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

T_RANGE_P3

T_RANGE_PMAX

T_RANGE_P1

12、修改表分区默认属性(ModifyDefaultAttributes)

修改表或表中分区的存储参数,对当前表和分区的存储参数没有影响,只有修改过之后,当你下次再

添加分区时,在不手工显式指定新分区参数的情况下,新分区默认使用你当前指定的存储参数。

有两种操作方式:

修改表属性,适用于range,list,hash分区形式(注意hash分区只能修改默认表空间参数)。例如:

JSSWEB>altertablet_partition_listmodifydefaultattributestablespacewebtbs;

表已更改。

修改分区属性,适用于组合分区,例如:

JSSWEB>altertablet_partition_rlmodifydefaultattributesforpartitiont_r_p2tablespacewebtbs;

表已更改。

13、修改表分区当前属性(ModifyPartition)

与上不同,该命令修改的不是默认属性,而是分区当前的存储属性,即修改即生效的那种,虽然号称

是修改当前分区属性,但实际上也有限制,比如所在表空间它就改不了(如果你想改,可以用movepartition

后面会讲到)

存储属性呢,三思一向没有过多关注(也许是因为从未有过因此导致的惨痛教训)此节跳过,留待有心

人自行查询文档:)

)

14、修改表子分区模板(SetSubpartitionTemplateTemplate)

既然是修改子分区模板,自然是只针对复合分区有效。修改分区模式不会改变当前的分区结构,只有

当你再增加、合并分区并且未显式指定子分区存储参数时,才会继承新分区模板中的参数。

该命令语法很简单:altertabletbnamesetsubpartition;

下面举个例子:

JSSWEB>selectsubpartition_name,tablespace_namefromuser_subpartition_templates

2wheretable_name='T_PARTITION_RH';

SUBPARTITION_NAMETABLESPACE_NAME

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

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

H1TBSPART01

H2TBSPART02

H3TBSPART03

H4TBSPART04

JSSWEB>altertablet_partition_rh

2setsubpartitiontemplate(

3subpartitionh1tablespacetbspart01,

4subpartitionh2tablespacetbspart02,

5subpartitionh3tablespacetbspart03);

表已更改。

JSSWEB>selectsubpartition_name,tablespace_namefromuser_subpartition_templates

2wheretable_name='T_PARTITION_RH';

SUBPARTITION_NAMETABLESPACE_NAME

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

H1TBSPART01

H2TBSPART02

H3TBSPART03

*这里又学到一个数据字典:user_subpartition_templates,用来查询表的分区模板信息。

如果说,想清除某表的分区模板,那就更简单了:

JSSWEB>selectsubpartition_name,tablespace_namefromuser_subpartition_templates

2wheretable_name='T_PARTITION_RL';

SUBPARTITION_NAMETABLESPACE_NAME

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

L1TBSPART01

L2TBSPART02

L3TBSPART03

L4TBSPART04

JSSWEB>altertablet_partition_rlsetsubpartitiontemplate();

表已更改。

JSSWEB>select*fromuser_subpartition_templateswheretable_name='T_PARTITION_RL';

未选定行

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

分区索引的管理

1(AddingIndexPartitions)

、增加索引分区

从语法上来讲,增加索引分区与增加表分区没有什么实际性差别,将table换成index即可:

Alterindexidxnameaddpartitionptnametbs_clause;

需要注意一点addpartition只能用于hashglobal索引(如果你想为range类型的索引增加分区,不要

add,split也许能帮你实际你的需求),并且addpartition无法新增local索引分区,因为local分区是由索

引所在基表来维护的。

下面举个操作的例子,还记的我们前面演示创建hash分区的时候创建的索引吗,这里就以它为例吧:

JSSWEB>selectpartition_name,tablespace_namefromuser_ind_partitions

2whereindex_name='IDX_PART_HASH_ID';

PARTITION_NAMETABLESPACE_NAME

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

SYS_P113TBSPART01

SYS_P114TBSPART02

SYS_P115TBSPART03

JSSWEB>alterindexidx_part_hash_idaddpartitioni_hash_id_p4tablespacetbspart04;

索引已更改。

JSSWEB>selectpartition_name,tablespace_namefromuser_ind_partitions

2whereindex_name='IDX_PART_HASH_ID';

PARTITION_NAMETABLESPACE_NAME

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

I_HASH_ID_P4TBSPART04

SYS_P113TBSPART01

SYS_P114TBSPART02

SYS_P115TBSPART03

看看,就是这么简单。

2、删除索引分区(DroppingIndexPartitions)

Droppartition只能操作global索引的range分区,语法也很简单:

Alterindexidxnamedroppartitionptname;

看起来很简单对吧,但是,需要注意,索引必须拥有一个maxvalue的分区,该分区无法删除。

另外,如果删除的索引分区中包含数据,分区被删除后,会造成相邻的higher分区失效,需要手工编

译!这个其实很容易理解,索引中数据都是经过排序的,我们droppartition删除的只是分区,但其对应的

索引数据还需要有地儿存在行啊(不然索引启不就不准确了)于是就只好存储到比它更高区间值的索引区分

里去了,那个分区莫名其妙多了数据,自然状态就为不可用了。

举个例子:

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

JSSWEB>selectpartition_name,high_value,tablespace_name,statusfromuser_ind_partitions

2whereindex_name='IDX_PART_RANGE_ID';

PARTITION_NAMEHIGH_VALUETABLESPACE_NAMESTATUS

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

I_RANGE_P110TBSPART01USABLE

I_RANGE_P240TBSPART02USABLE

I_RANGE_PMAXMAXVALUETBSPART03USABLE

向表中插入几条记录:

JSSWEB>insertintot_partition_rangevalues(8,'a');

已创建1行。

JSSWEB>insertintot_partition_rangevalues(9,'b');

已创建1行。

JSSWEB>commit;

提交完成。

执行删除操作

JSSWEB>alterindexidx_part_range_iddroppartitioni_range_p1;

索引已更改。

JSSWEB>selectpartition_name,high_value,tablespace_name,statusfromuser_ind_partitions

2whereindex_name='IDX_PART_RANGE_ID';

PARTITION_NAMEHIGH_VALUETABLESPACE_NAMESTATUS

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

I_RANGE_P240TBSPART02UNUSABLE

I_RANGE_PMAXMAXVALUETBSPART03USABLE

于是,i_range_p2分区就unusable了,继续往下看吧,后面要讲如何重编译索引分区了。

3、重编译索引分区(RebuildingIndexPartitions)

一生不如意,十有八九。碰上索引分区无效也不见得就是撞头彩的运气,这个东西还是黑常见的,比

如分区表操作时未指定updateindexes子句就极有可能造成索引分区的无效,一般情况下,你都可以通过:

Alterindexidxnamerebuildpartition/subpartitionptname;

重新编译。注意global索引只支持range分区,local索引无限制。

例如:

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

JSSWEB>alterindexidx_part_range_idrebuildpartitioni_range_p2;

索引已更改。

JSSWEB>selectpartition_name,high_value,tablespace_name,statusfromuser_ind_partitions

2whereindex_name='IDX_PART_RANGE_ID';

PARTITION_NAMEHIGH_VALUETABLESPACE_NAMESTATUS

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

I_RANGE_P240TBSPART02USABLE

I_RANGE_PMAXMAXVALUETBSPART03USABLE

而对于local索引分区,你还可以使用这种命令方式:

altertabletbnamemodifypartition/subpartitionptnamerebuildunusablelocalindexes;

4、重命名索引分区(RenamingIndexPartitions)

与表分区中改名功能相同,索引分区重命名也仅只是改个名字而已,语法非常简单:

Alterindexidxnamerenamepartition/subpartitionptnametoptnewname;

这个功能没啥可说的,使用也很简单:

JSSWEB>alterindexidx_part_range_idrenamepartitioni_range_p2toi_range_p1;

索引已更改。

同样需要注意,global分区只能够支持range分区,local索引无限制。

5、分拆索引分区(SplittingIndexPartitions)

Splitpartiton操作只能操作global索引分区(local分区会自动维护)且只能操作global索引分区中range

类型的分区。

语法与表分区的操作很类似:

Alterindexidxnamesplitpartitionptnameat(value)into(partitionpt1tbsclause,partitionpt2tbsclause);

看个例子:

JSSWEB>alterindexidx_part_range_idsplitpartitioni_range_p1at(10)into

2(partitioni_range_p1tablespacetbspart01,

3partitioni_range_p2tablespacetbspart02);

索引已更改。

JSSWEB>selectpartition_name,high_value,tablespace_name,statusfromuser_ind_partitions

2whereindex_name='IDX_PART_RANGE_ID';

PARTITION_NAMEHIGH_VALUETABLESPACE_NAMESTATUS

三思笔记]全面学习分区表及分区索引QQ群:59666289/QQ5454589君三思

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

I_RANGE_P110TBSPART01USABLE

I_RANGE_PMAXMAXVALUETBSPART03USABLE

I_RANGE_P240TBSPART02USABLE

6、修改索引分区默认属性(ModifyingDefaultAttributesofIndexPartitions)

修改索引分区默认属性,与修改表分区的操作没什么区别,不过对于global索引,你只能修改range

分区,local索引则无此限制。

语法上小有差异:Alterindexidxnamemodifydefaultattributesforpartitionptname;

不做演示!

7、修改索引分区当前属性(ModifyingRealAttributesofIndexPartitions)

同样global索引只支持range分区的修改,支持所有local索引,其它与表分区修改同理,不做演示!

全篇完结之后记

原计划还想花重量篇幅多介绍一些实践,比如分区表的常见使用方式,对于效率提升的比较,不同情况下,

使用global索引与local索引的区别,什么情况下会造成索引失效,什么时候需要重新编译等待~~~待到行笔处

却发现千言万语,又不知从何处开始。

越学越觉着oracle博大精深,确实不是盖的,小小一个分区就能引出这么多文章,还无法一一道进。因此,

原计划起的“深入学习分区表分区表及分区索引”写到最后也是越写也没自信,越写越觉着我所了解到的和我

所能介绍的不过都是皮毛罢了,因此,改名吧。“全面认识oracle分区表及分区索引”就此登场~

本系列全文已打包处理为pdf,并上传至pub论坛:/,供有心者参阅方便~~

全文不过一家之言,虽在成文之前也多有参考前辈们的精华,但未免仍有纰漏,如有问题,欢迎大家就此

与我沟通,交流。

我常在的QQ群:59666289,欢迎大家加入讨论:)

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289

[三思笔记]单条SQL语句实现复杂逻辑几例

/958526/9

58526.html

[三思笔记]一步一步学Dataguard

/958526/9

58526.html

[三思笔记]使用可传输表空间的特性复制数据

/

[三思笔记]日期时间及数字的格式化参数大全

/

[三思笔记]RMAN高级应用之Duplicate复制数据库

/

[]RHELAS4oracle10g10.2.0.3

三思笔记下升级oracle10g

/

[三思笔记]RHELAS4下安装32oracle10g

/

[三思笔记]Statspack初步学和用

/

[三思笔记]oracle著名及非著名函数介绍

/

[三思笔记]一步一步学rman

/

[三思笔记]学习动态性能表

/

三思笔记]全面学习分区表及分区索引/QQ5454589君三思QQ群:59666289