Welcome 微信登录

首页 / 数据库 / MySQL / 详述Oracle 11g中的Reference Partition

Data Partition是Oracle早期提出的一项针对大数据对象的解决方案。经过若干版本的演变,Partition依然是目前比较流行、应用广泛并且接受程度较高的技术策略。从Oracle产品线角度,Partition的成功是与Oracle不断丰富完善分区技术和方案是分不开的。在每一个版本中,Partition技术都推出一些新的进步和发展。无论是8、8i还是11g、12c,Partition技术都是在不断的向前进步,来满足更加复杂的实际应用需求。本篇主要介绍11g新推出的Reference Partitioin。Reference Partition针对的业务场景是主外键关联。主表分区之后,借助Reference Partition可以实现自动的子表分区(不管子表上有无分区键)。经过Reference Partition分区之后,在同一个主表分区中的数据记录,对应到的子表记录,全部都在相同的子表分区上。这种特性和分区类型,从性能和管理两个方面,都可以给日常运维带来很多好处方便。下面笔者将通过一系列实验来介绍Reference Partiton。1、实验环境介绍笔者选择Oracle 11g进行测试,具体版本为11.2.0.4。SQL> select * from v$version;BANNER-----------------------------------Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit ProductionPL/SQL Release 11.2.0.4.0 - ProductionCORE    11.2.0.4.0 ProductionTNS for Linux: Version 11.2.0.4.0 - ProductionNLSRTL Version 11.2.0.4.0 – Production2、Reference Partition数据表创建和普通主外键数据表创建没有过多差异,首先我们需要创建带分区的主表。SQL> create table t_master  2  ( object_id number,  3    owner varchar2(100),  4    object_name varchar2(100),  5    object_type varchar2(100)  6  )  7  partition by list(owner) –List分区类型  8  (  9    partition p0 values ("PUBLIC"), 10    partition p1 values ("SYS"), 11    partition p3 values (default) 12  ) 13  ;--添加主键约束SQL> alter table t_master add constraint pk_t_master primary key (object_id);Table altered创建子表,注意:Reference Partition并不要求子表中包括分区键,引用关系就是子表的分区依据。另外:使用Reference Partition要求创建子表和定义外键约束在同一个语句中。SQL> create table t_detail  2  ( object_id number,  3    master_id number,  4    obj_comment varchar2(100),  5    obj_type varchar2(100),  6    constraint fk_mas_det foreign key (master_id) references t_master(object_id)  7  ) partition by reference(fk_mas_det); create table t_detail( object_id number,  master_id number,  obj_comment varchar2(100),  obj_type varchar2(100),  constraint fk_mas_det foreign key (master_id) references t_master(object_id)) partition by reference(fk_mas_det)ORA-14652: 不支持引用分区外键我们收到了一个Oracle报错。首先我们看一下定义reference partition的语法,在create table语句中要创建定义好外键约束的名称。之后,利用partition by语句,将外键作为划分依据进行定义。当前报错ORA-14652,检查一下官方对于这个错误的解释。[oracle@localhost ~]$ oerr ora 1465214652, 00000, "reference partitioning foreign key is not supported"// *Cause:  The specified partitioning foreign key was not supported//          for reference-partitioned tables. All columns of the//          partitioning foreign key must be constrained NOT NULL with//          enabled, validated, and not deferrable constraints. Furthermore,//          a virtual column cannot be part of the partitioning foreign key.//* Action: Correct the statement to specify a supported//          partitioning foreign key.说明中提示了错误原因,如果使用Reference Partition,外键列是不允许为空的。标准外键定义并没有规定外键列必须为空,但是如果使用引用分区技术,就必须要求外键列不能为空。这种约束其实也好理解。Reference Partition不需要明确指定分区键,但是实际上还是需分区键(或者称为分区因素)。如果没有外键值,也就失去了到主表分区的定位功能,Oracle必然不会允许创建。修改建表语句如下:SQL> create table t_detail  2  ( object_id number,  3    master_id number not null,  4    obj_comment varchar2(100),  5    obj_type varchar2(100),  6    constraint fk_mas_det foreign key (master_id) references t_master(object_id)  7  ) partition by reference(fk_mas_det);Table created下面从分区表角度观察两个数据表。SQL> select partition_name, high_value, partition_position from dba_tab_partitions where table_owner="SYS" and table_name="T_MASTER";PARTITION_NAME      HIGH_VALUE      PARTITION_POSITION-------------------- --------------- ------------------P0                  "PUBLIC"                        1P1                  "SYS"                            2P3                  default                          3SQL> select partition_name, high_value, partition_position from dba_tab_partitions where table_owner="SYS" and table_name="T_DETAIL";PARTITION_NAME      HIGH_VALUE      PARTITION_POSITION-------------------- --------------- ------------------P0                                                    1P1                                                    2P3                                                    3注意两点:子表t_detail的high_value列为空,说明该数据表并没有一个明确的分区键,主表分区键owner在子表中也不存在。另外,子表分区结构、数量和名称与主表完全相同。从段结构segment上,我们可以看到11g的defered segment creation并没有应用。SQL> select segment_name, partition_name, segment_type from dba_segments where owner="SYS" and segment_name in ("T_MASTER","T_DETAIL");SEGMENT_NAME    PARTITION_NAME      SEGMENT_TYPE--------------- -------------------- ----------------------T_MASTER        P3                  TABLE PARTITIONT_MASTER        P1                  TABLE PARTITIONT_MASTER        P0                  TABLE PARTITIONT_DETAIL        P3                  TABLE PARTITIONT_DETAIL        P1                  TABLE PARTITIONT_DETAIL        P0                  TABLE PARTITION6 rows selected3、数据插入实验下面进行数据插入和分区分布实验。首先进行主表数据插入:SQL> insert into t_master select object_id, owner, object_name, object_type from dba_objects;120361 rows insertedSQL> commit;Commit completeSQL> exec dbms_stats.gather_table_stats(user,"T_MASTER",cascade => true);PL/SQL procedure successfully completed子表数据插入:SQL> insert into t_detail select seq_t_detail.nextval, object_id, object_name, object_type from dba_objects where object_name not in ("SEQ_T_DETAIL");120361 rows insertedSQL> commit;Commit completeSQL> exec dbms_stats.gather_table_stats(user,"T_DETAIL",cascade => true);PL/SQL procedure successfully completed按照当前的数据关系,应该是一条主表记录,对应一条子表记录的关系。我们检查数据字典情况。SQL> select table_name, partition_name, high_value,num_rows from dba_tab_partitions where table_owner="SYS" and table_name in ("T_MASTER");TABLE_NAME        PARTITION_NAME      HIGH_VALUE        NUM_ROWS------------------------------ -------------------- --------------- ----------T_MASTER          P0                  "PUBLIC"            33996T_MASTER          P1                  "SYS"                37817T_MASTER          P3                  default              48548SQL> select table_name, partition_name, high_value,num_rows from dba_tab_partitions where table_owner="SYS" and table_name in ("T_DETAIL");TABLE_NAME        PARTITION_NAME      HIGH_VALUE        NUM_ROWS------------------------------ -------------------- --------------- ----------T_DETAIL          P0                                        33996T_DETAIL          P1                                        37817T_DETAIL          P3                                        48548数据分布正确。说明:子表分区分布的依据完全在于主表记录对应的分区编号。相同主表分区记录对应的子表记录,一定在相同的子表分区上。不同主表分区记录对应的子表记录,不可能在相同的子表分区上。为便于实验,多插入一些数据:SQL> insert into t_detail select seq_t_detail.nextval, object_id, object_name, object_type from dba_objects where object_name not in ("SEQ_T_DETAIL");120361 rows insertedSQL> commit;Commit completeSQL> exec dbms_stats.gather_table_stats(user,"T_DETAIL",cascade => true);PL/SQL procedure successfully completedSQL> select table_name, partition_name, high_value,num_rows from dba_tab_partitions where table_owner="SYS" and table_name in ("T_DETAIL");TABLE_NAME    PARTITION_NAME      HIGH_VALUE        NUM_ROWS------------------------------ -------------------- --------------- ----------T_DETAIL      P0                                        67992T_DETAIL      P1                                        75634T_DETAIL      P3                                        97096那么,Reference Partition在实际运维场景下的意义在于何处呢?经过笔者之前的讨论,Partition技术的出发点无非在于性能和管理两个角度。性能上最典型的代表是分区裁剪、本地索引;管理最典型代表就是分区摘除、Swip分区归档。最早期Partition是针对性能方面因素比较多,近年来随着硬件性能的提升,管理方面带来的优势,越来越受到重视。下篇中,我们将从性能和管理两个角度,讨论Reference Partition的作用。更多Oracle相关信息见Oracle 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=12本文永久更新链接地址