设为首页 收藏本站
查看: 867|回复: 0

[经验分享] 深入解析partition-hash分区

[复制链接]

尚未签到

发表于 2017-7-2 16:04:52 | 显示全部楼层 |阅读模式
  依据惯例,先看官网对hash partition的解释

    Hash partitioning enables easy partitioning of data that does not lend itself to range or list partitioning. It does this with a simple syntax and is easy to implement. It is a  better choice than range partitioning when:
■ You do not know beforehand how much data maps into a given range
■ The sizes of range partitions would differ quite substantially or would be difficult to balance manually
■ Range partitioning would cause the data to be undesirably clustered
■ Performance features such as parallel DML, partition pruning, and partition-wise
joins are important
    The concepts of splitting, dropping or merging partitions do not apply to hash partitions. Instead, hash partitions can be added and coalesced.
1、创建hash partition
语法如下:
DSC0000.png 3
语法看起来比range partition复杂,实际要简单的多。
column: 分区依赖列 ( 支持多个,中间以逗号分隔 );
partition: 指定分区,有两种方式:
    直接指定分区名,分区所在表空间等信息。
    只指定分区数量,和可供使用的表空间。
例:
--创建hash分区表
SQL> create table t_partition_hash(id number,name varchar2(20))
  2 partition by hash(id)(
  3 partition t_hash_p1 tablespace tbs01,
  4 partition t_hash_p2 tablespace tbs02,
  5 partition t_hash_p3 tablespace tbs03);

表已创建。
--查看hash分区表分区信息
SQL> edit
已写入 file afiedt.buf

  1 select partition_name,high_value,tablespace_name from user_tab_partitions
  2* where table_name='T_PARTITION_HASH'
SQL> /

PARTITION_NAME HIGH_VALUE TABLESPACE_NAME
------------------------------ ---------------------------------------------------------------------
T_HASH_P1     TBS01
T_HASH_P2     TBS02
T_HASH_P3     TBS03
--指定分区数量及表空间,创建相同的hash分区表
SQL> drop table t_partition_hash;

表已删除。

SQL> edit
已写入 file afiedt.buf

  1 create table t_partition_hash(id number,name varchar2(20))
  2 partition by hash(id)
  3* partitions 3 store in(tbs01,tbs02,tbs03)
SQL> /

表已创建。

SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
SYS_P21     TBS01
SYS_P22     TBS02
SYS_P23     TBS03
提示: 这里分区数量和可供使用的表空间数量之间没有直接对应关系。 分区数并不一定要等于表 空间数。
例如:
--指定分区数量<指定表空间数量
SQL> edit
已写入 file afiedt.buf

  1 create table t_partition_hash(id number,name varchar2(20))
  2 partition by hash(id)
  3* partitions 3 store in(tbs01,tbs02,tbs03,jjjg)
SQL> /

表已创建。

SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
SYS_P24     TBS01
SYS_P25     TBS02
SYS_P26     TBS03
--指定分区数量>指定表空间数量
SQL> edit
已写入 file afiedt.buf

  1 create table t_partition_hash(id number,name varchar2(20))
  2 partition by hash(id)
  3* partitions 3 store in(tbs01,tbs02)
SQL> /

表已创建。

SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
SYS_P27 TBS01
SYS_P28 TBS02
SYS_P29 TBS01
2、hash分区表上创建索引
2.1、创建global分区索引
SQL> create index idx_part_hash_id on t_partition_hash(id)
  2 global partition by hash(id)
  3 partitions 3 store in(tbs01,tbs02,tbs03);

索引已创建。
SQL> edit
已写入 file afiedt.buf

  1 select partition_name,tablespace_name from user_ind_partitions
  2* where index_name='IDX_PART_HASH_ID'
SQL> /

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
SYS_P30     TBS01
SYS_P31     TBS02
SYS_P32     TBS03
2.2、创建local分区索引
SQL> drop index idx_part_hash_id;

索引已删除。

SQL> create index idx_part_hash_id on t_partition_hash(id) local;

索引已创建。

SQL> select partition_name,tablespace_name from user_ind_partitions
  2 where index_name='IDX_PART_HASH_ID';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
SYS_P27     TBS01
SYS_P28     TBS02
SYS_P29     TBS01
由此可见,hash分区的local索引与range 分区的local索引一样,其local 索引的分区完全继承表的分区的属性。
综上提示:
1、对于 global 索引分区而言,在 10g 中只能支持 range 分区和 hash 分区。
2、对于 local 索引分区而言,其分区形式完全依赖于索引所在表的分区形式。
3、注意,在创建索引时如果不显式指定 global 或 local ,则默认是 global 。
4、注意,在创建 global 索引时如果不显式指定分区子句,则默认不分区 。
3、分区表的管理
3.1增加表分区(add partition)
语法:alter table tbname add partition ptname……
例:
SQL> alter table t_partition_hash add partition t_hash_p4 tablespace tbs03;

表已更改。

SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
SYS_P27 TBS01
SYS_P28 TBS02
SYS_P29 TBS01
T_HASH_P4 TBS03
注意:
1 、对于 hash 分区,当你执行 add partition 操作的时候, oracle 会自动选择一个分区,并重新分配部分
记录到新建的分区,这也意味着有可能带来一些 IO 操作。
2 、执行 alter table 时未指定 update indexes 子句:
如果是 range/list 分区,其 local 索引和 global 索引不会受影响 ;
如果是 hash 分区,新加分区及有数据移动的分区的 local 索引和 glocal 索引会被置为 unuseable ,需要重新编译。
3.2、收缩表分区(coalesce partitions)
Coalesce partition 仅能被应用于 hash 分区或复合分区的 hash 子分区,执行 之后,会自动收缩当前的表分区,一次只能减少一个分区,
不能指定减少partitoin的名称,当表只剩一个分区时,再执行coalesce patition会报错。此功能相当于range 和ist分区表的merge partition
例:
SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
SYS_P27 TBS01
SYS_P28 TBS02
SYS_P29 TBS01
T_HASH_P4 TBS03

SQL> alter table t_partition_hash coalesce partition sys_p27;
alter table t_partition_hash coalesce partition sys_p27
                                                *
第 1 行出现错误:
ORA-14174: 仅 <并行子句> 可以跟在 COALESCE PARTITION|SUBPARTITION 之后


SQL> alter table t_partition_hash coalesce partition;

表已更改。

SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
SYS_P27 TBS01
SYS_P28 TBS02
SYS_P29 TBS01
--再执行一次coalesce partition
SQL> alter table t_partition_hash coalesce partition;

表已更改。

SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
SYS_P27 TBS01
SYS_P28 TBS02

注意,收缩的只是分区,并不会影响到数据,但是视被收缩分区中数据的多少,收缩表分区也会涉及 到 IO 操作。 另外如果你在执行该语句时没有指定 update indexes 子句,收缩过程中有数据改动的分区其 local 索引 和 glocal 索引都会失效,需要重新编译。
3.3、交换表分区(Exchange partition)
上一章节讲range分区中提到exchange partition,其实就是数据迁移。hash partition可以与非分区表及range分区表(注意必须是range的组合分区range-hash,而且必须是range-hash与hash进行交换,即alter table tb_partiotn_range_hash exchange partition ptname with table tb_partition_hash,后面会有实例详细演示)进行exchange partition。
3.3.1 range partition与hash partition相互exchange partition(不支持)
--hash partition insert
SQL> insert into t_partition_hash values(1,'a');

已创建 1 行。

SQL> insert into t_partition_hash values(11,'b');

已创建 1 行。

SQL> insert into t_partition_hash values(21,'c');

已创建 1 行。

SQL> commit;
提交完成。

SQL> select * from t_partition_hash;

        ID NAME
---------- --------------------
        11 b
         1 a
        21 c

SQL> select * from t_partition_hash partition(t_hash_p1);

        ID NAME
---------- --------------------
        11 b

SQL> select * from t_partition_hash partition(t_hash_p2);

        ID NAME
---------- --------------------
         1 a

SQL> select * from t_partition_hash partition(t_hash_p3);

        ID NAME
---------- --------------------
        21 c
通过以上insert 语句可以看出,hash partition表中分区内的数据存储无规律,人为无法识别新插入的数据将存放于哪个分区。
--range partition insert
SQL> insert into t_partition_range values(11,'a');

已创建 1 行。

SQL> insert into t_partition_range values(21,'b');

已创建 1 行。

SQL> commit;
--hash partition table exchange partition with range partition table
SQL> alter table t_partition_hash exchange partition t_hash_p1
  2 with table t_partition_range;
with table t_partition_range
           *
第 2 行出现错误:
ORA-14095: ALTER TABLE EXCHANGE 要求非分区, 非聚簇的表

--range partition table exchange partition with  hash partition table
SQL> alter table t_partition_range exchange partition p2
  2 with table t_partition_hash;
with table t_partition_hash
           *
第 2 行出现错误:
ORA-14095: ALTER TABLE EXCHANGE 要求非分区, 非聚簇的表
结论:由此可见hash分区表与range分区表无法进行exchange partition操作

3.3.2 range-hash partition exchange partition hash partition(支持,反过来交换则不支持)
--创建range-hash表
SQL> create table t_partition_range_hash(id number,name varchar2(20))
  2 partition by range(id) subpartition by hash(name)
  3 subpartitions 3 store in(tbs01,tbs02,tbs03)(
  4 partition t_range_p1 values less than(10) tablespace tbs01,
  5 partition t_range_p2 values less than(20) tablespace tbs02,
  6 partition t_range_p3 values less than(30) tablespace tbs03,
  7 partition t_range_pmax values less than(maxvalue) tablespace tbs03);

表已创建。
SQL> edit
已写入 file afiedt.buf

  1 alter table t_partition_range_hash exchange partition t_range_p2
  2* with table t_partition_hash
SQL> /
alter table t_partition_range_hash exchange partition t_range_p2
*
第 1 行出现错误:
ORA-14295: 分区列和子分区列之间的列的类型或大小不匹配
注意:range-hash分区表与hash分区表进行exchange partition操作时,hash分区依赖字段和类型必须一致,上例中报错是因为
t_partition_range_hash表是根据name进行subpartition的hash分区,但t_partition_hash表是根据id进行hash分区。所以会报上面的
ora-14295错误。
--创建根据name进行hash分区的t_partition_hash_tmp表,如下:
SQL> create table t_partition_hash_tmp(id number,name varchar2(20))
  2 partition by hash(name)
  3 partitions 3 store in(tbs01,tbs02,tbs03);

表已创建。

SQL> insert into t_partition_hash_tmp values(1,'a');

已创建 1 行。

SQL> insert into t_partition_hash_tmp values(12,'b');

已创建 1 行。

SQL> commit;

提交完成。
--执行range-hash exchange partition with hash
SQL> edit
已写入 file afiedt.buf

  1 alter table t_partition_range_hash exchange partition t_range_p2
  2* with table t_partition_hash_tmp
SQL> /
with table t_partition_hash_tmp
           *
第 2 行出现错误:
ORA-14099: 未对指定分区限定表中的所有行

注意:因为t_partition_hash_tmp表中数据id=1的记录,不在t_partition_range_hash中t_range_p2分区范围内,所以会报错,如上节讲到的
,可利用without validation强制执行交换。如下所示:

SQL> edit
已写入 file afiedt.buf

  1 alter table t_partition_range_hash exchange partition t_range_p2
  2* with table t_partition_hash_tmp without validation
SQL> /

表已更改。
--查询交换后的 t_partition_range_hash表数据
SQL> select * from t_partition_range_hash;

        ID NAME
---------- --------------------
         1 a
        12 b
3.3.3 range-hash partition与range partition进行exchange partition(不支持)
SQL> edit
已写入 file afiedt.buf

  1 alter table t_partition_range exchange partition p2
  2* with table t_partition_range_hash
SQL> /
with table t_partition_range_hash
           *
第 2 行出现错误:
ORA-14095: ALTER TABLE EXCHANGE 要求非分区, 非聚簇的表
3.3.4 range-hash partition与非分区表进行exchange partition(不支持)
SQL> alter table t_partition_range_hash exchange partition t_range_p2
  2 with table t_partition_range_tmp;
with table t_partition_range_tmp
           *
第 2 行出现错误:
ORA-14291: 不能用非分区表 EXCHANGE 组合分区
SQL> select * from t_partition_hash;

        ID NAME
---------- --------------------
        11 b

SQL> insert into t_partition_hash values(1,'a');

已创建 1 行。

SQL> insert into t_partition_hash values(31,'c');

已创建 1 行。

SQL> commit;

提交完成。

3.3.5 hash partition exchange partition with range-hash partition(不支持)
SQL> alter table t_partition_hash exchange partition t_hash_p1
  2 with table t_partition_range_hash;
with table t_partition_range_hash
           *
第 2 行出现错误:
ORA-14095: ALTER TABLE EXCHANGE 要求非分区, 非聚簇的表
3.4、截断表分区(Truncate partition)
同上一篇range分区的truncate partition用法功能一样。
语法简单:alter table tbname truncate partition/subpartition ptname;
例:
SQL> select * from t_partition_hash;

        ID NAME
---------- --------------------
        11 b
        12 c
         1 a

SQL> select * from t_partition_hash partition(t_hash_p1);

        ID NAME
---------- --------------------
        11 b

SQL> alter table t_partition_hash truncate partition t_hash_p1;

表被截断。

SQL> select * from t_partition_hash partition(t_hash_p1);

未选定行
3.5、移动表分区(Move Partition)
同上一篇range分区的move partition用法功能一样,主要用来修改表分区所在的表空间。
语法:alter table tbname move partition/subpartition ptname……。
例:
SQL> EDIT
已写入 file afiedt.buf

  1 select partition_name,tablespace_name from user_tab_partitions
  2* where table_name='T_PARTITION_HASH'
SQL> /

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
T_HASH_P1 TBS01
T_HASH_P2 TBS02
T_HASH_P3 TBS03

SQL> alter table t_partition_hash move partition t_hash_p1 tablespace jjjg;

表已更改。

SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
T_HASH_P1 JJJG
T_HASH_P2 TBS02
T_HASH_P3 TBS03
3.6、重命名表分区(Rename Partition)
语法:alter table tbname rename partition ptname to newptname;
语法和用法都简单,上一篇也讲到过,在此不多说。直接看例子:
SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
T_HASH_P1 JJJG
T_HASH_P2 TBS02
T_HASH_P3 TBS03

SQL> alter table t_partition_hash rename partition t_hash_p1 to t_hash_p1_new;

表已更改。

SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
T_HASH_P1_NEW JJJG
T_HASH_P2 TBS02
T_HASH_P3 TBS03
3.7、hash分区表无法进行drop、merge、split分区操作
与range分区不同,hash分区不能进行drop partition、merge partition(hash分区可用coalesce partition代替)、split partition(hash分区可用add partition代替)操作。详见下面例子
SQL> select partition_name,tablespace_name from user_tab_partitions
  2 where table_name='T_PARTITION_HASH';

PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
T_HASH_P1_NEW JJJG
T_HASH_P2 TBS02
T_HASH_P3 TBS03

--测试执行drop partition
  1* alter table t_partition_hash drop partition t_hash_p1_new
SQL> /
alter table t_partition_hash drop partition t_hash_p1_new
                                            *
第 1 行出现错误:
ORA-14255: 未按范围, 组合范围或列表方法对表进行分区

--测试执行merge partition
SQL> alter table t_partition_hash merge partitions t_hash_p2,t_hash_p3 into partition t_has
alter table t_partition_hash merge partitions t_hash_p2,t_hash_p3 into partition t_hash_new
            *
第 1 行出现错误:
ORA-14255: 未按范围, 组合范围或列表方法对表进行分区

--测试执行split partition
SQL> edit
已写入 file afiedt.buf

  1 alter table t_partition_hash split partition t_hash_p2 at(20) into(
  2 partition t_hash_p2_1 tablespace tbs01,
  3* partition t_hash_p2_2 tablespace tbs02)
SQL> /
alter table t_partition_hash split partition t_hash_p2 at(20) into(
            *
第 1 行出现错误:
ORA-14255: 未按范围, 组合范围或列表方法对表进行分区

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-390450-1-1.html 上篇帖子: RabbitMQ第四篇:Spring集成RabbitMQ 下篇帖子: Spring 消息
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表