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)
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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分区中,比如按照时间划分,2008年1季度的数据放到a分区,08年2季度的数据放到b
分区,因此在创建的时候呢,需要你指定基于的列,以及分区的范围值,如果某些记录暂无法预测范围,可以
创建maxvalue分区,所有不在指定范围内的记录都会被存储到maxvalue所在分区中,并且支持指定多列做为
依赖列,后面在讲how的时候会详细谈到。
二、When使用Hash分区
通常呢,对于那些无法有效划分范围的表,可以使用hash分区,这样对于提高性能还是会有一定的帮助。
hash分区会将表中的数据平均分配到你指定的几个分区中,列所在分区是依据分区列的hash值自动分配,因此
你并不能控制也不知道哪条记录会被放到哪个分区中,hash分区也可以支持多个依赖列。
三、When使用List分区
List分区与range分区和hash分区都有类似之处,该分区与range分区类似的是也需要你指定列的值,但这
又不同与range分区的范围式列值---其分区值必须明确指定,也不同与hash分区---通过明确指定分区值,你能
控制记录存储在哪个分区。它的分区列只能有一个,而不能像range或者hash分区那样同时指定多个列做为分
区依赖列,不过呢,它的单个分区对应值可以是多个。
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思QQ群:59666289
你在分区时必须确定分区列可能存在的值,一旦插入的列值不在分区范围内,则插入/更新就会失败,因此
通常建议使用list分区时,要创建一个default分区存储那些不在指定范围内的记录,类似range分区中的maxvalue
分区。
四、When使用组合分区
如果某表按照某列分区之后,仍然较大,或者是一些其它的需求,还可以通过分区内再建子分区的方式将
分区再分区,即组合分区的方式。
组合分区呢在10g中有两种:range-hash,range-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:分区依赖列(如果是多个,以逗号分隔);
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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,
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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_indexes、user_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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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;
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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);
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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_indexes、user_ind_partitions两个数据字典,不再举例。
创建Local索引③
在前面学习range分区时,我们已经对Local索引的特性做了非常清晰的概述,因此这里也不再举
例,如有疑问,建议再仔细复习range分区的相关示例,如果还有疑问,当面问我好了:)
综上:
对于global索引分区而言,在10g中只能支持range分区和hash分区,因此后续示例中不会再提
及。
对于local索引分区而言,其分区形式完全依赖于索引所在表的分区形式,不管从创建语法还是理
解难度均无技术含量,因此后续也不再提供示例。
注意,在创建索引时如果不显式指定global或local,则默认是global。
注意,在创建global索引时如果不显式指定分区子句,则默认不分区(废话)。
3、创建list分区
创建语法如下:[图:list_]
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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:分区的存储属性,例如所在表空间等属性(可为空),默认继承基表所在表空间的
属性。
组合分区相对于普通分区,语法上稍稍复杂了一些,但也正因如此,其子分区的创建可以非常灵活,
下面分别举几个例子(注:仅示例,并非穷举所有形式)
①为所有分区各创建4个hash子分区
/QQ:5454589君三思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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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
-----------------------------------------------------------------
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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_indexes、user_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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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三思笔记]全面学习分区表及分区索引/QQ:5454589君三思
增加分区支持支持支持支持支持除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)
修改分区当前属性全局支持///无
本地////
全局支持///无
本地////
全局支持///无
本地支持支持支持支持无
QQ:5454589君三思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这种存在范围值的分区,所要增加的分区值必须要大于当前分区中的
最大值(如果当前存在maxvalue或default的分区,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);
表已更改。
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思QQ群:59666289
Hash和list的语法与上类似,这里不再举例。
注意:
1、对于hash分区,当你执行addpartition操作的时候,oracle会自动选择一个分区,并重新分配部分
记录到新建的分区,这也意味着有可能带来一些IO操作。
2、执行altertable时未指定updateindexes子句:
如果是range/list分区,其local索引和global索引不会受影响;
如果是hash分区,新加分区及有数据移动的分区的local索引和glocal索引会被置为unuseable,
需要重新编译。
3、复合分区完全适用上述所述规则。
2、收缩表分区(coalescepartitions)
Coalescepartition是个很有意思的分区功能,仅能被应用于hash分区或复合分区的hash子分区,执行
之后,会自动收缩当前的表分区,比如某表当前有5个hash分区,执行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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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适用于所有分区格式,你可以将数据从分区表迁移到非
分区表,也可以从非分区表迁移至分区表,或者从hashpartition到rangepartition诸如此类吧。
其语法很简单:altertabletbname1exchangepartition/subpartitionptnamewithtabletbname2;
Exchangepartition迁移的方式也很有意思,言语表达怕大家听不明白,下面直接通过示例来表达:
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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);
未选定行
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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);
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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后,数据仍然转换
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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);
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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的分区。
该命令的语法针对不同分区会有不同的形式,
Forrangepartition:altertabletbnamesplitpartitionptnameat(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);
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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视被分隔的分区数据量多少,
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思QQ群:59666289
据的全扫描,我们也许可以形容为:fullpartitionscan:),除非:
Split后的两个分区中,至少有一个是空的,并且非空的那个分区的存储属性与split前的存储
属性完全相同
如果split的分区包含lob字段,split后非空的那个分区中该字段的存储属性也必须与split前
的存储属性完全相同。
这种情况下的splitpartition/subpartition也会非常高效,oracle会自动进行优化,此时的分区操作类
似于addpartition。
通常情况下,如果在执行splitpartition/subpartition时,如果没有指定updateindexes子句,都会造
成local和global索引的失效。注意,我们说的是通常,如果你splitpartition/subpartition的是个空分区,或
者没有触发任何数据移动或变化,那么即使不加updateindexes,也不会影响到索引。当然,保险起见,建
议你还是执行完之后,查询一下数据字典,确认一下当前索引的状态。
9、截断表分区(TruncatePartition)
Truncatepartition就像truncatetable一样,直接从头部截断数据,用来删除数据那是效率超高无比。但
是如果该表有外键引用的话,ddl的truncate就不好使了,这时候你只能要么使用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)
Movepartition与modifypartition的功能相似,但又比之更加强劲,比如可以修改分区所在表空间等等,
与movetable的操作很类似,某些时间也非常有用,比如降低行迁移。语法很简单:
Altertabletbnamemovepartition/subpartition;
例如:
JSSWEB>selectpartition_name,tablespace_namefromuser_tab_partitions
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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';
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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
-------------------------------------------------
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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';
未选定行
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思QQ群:59666289
分区索引的管理
1(AddingIndexPartitions)
、增加索引分区
从语法上来讲,增加索引分区与增加表分区没有什么实际性差别,将table换成index即可:
Alterindexidxnameaddpartitionptnametbs_clause;
需要注意一点addpartition只能用于hash的global索引(如果你想为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删除的只是分区,但其对应的
索引数据还需要有地儿存在行啊(不然索引启不就不准确了),于是就只好存储到比它更高区间值的索引区分
里去了,那个分区莫名其妙多了数据,自然状态就为不可用了。
举个例子:
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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索引无限制。
例如:
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思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/QQ:5454589君三思
---------------------------------------------------------------
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,欢迎大家加入讨论:)
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思QQ群:59666289
[三思笔记]单条SQL语句实现复杂逻辑几例
/958526/9
58526.html
[三思笔记]一步一步学Dataguard
/958526/9
58526.html
[三思笔记]使用可传输表空间的特性复制数据
/
[三思笔记]日期时间及数字的格式化参数大全
/
[三思笔记]RMAN高级应用之Duplicate复制数据库
/
[]RHELAS4oracle10g10.2.0.3
三思笔记下升级oracle10g到
/
[三思笔记]RHELAS4下安装32位oracle10g
/
[三思笔记]Statspack初步学和用
/
[三思笔记]oracle著名及非著名函数介绍
/
[三思笔记]一步一步学rman
/
[三思笔记]学习动态性能表
/
三思笔记]全面学习分区表及分区索引/QQ:5454589君三思QQ群:59666289


发布评论