阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Oracle 11g新特性:引用分区(reference partitioning)

193次阅读
没有评论

共计 5878 个字符,预计需要花费 15 分钟才能阅读完成。

引用分区 (reference partitioning) 是 Oracle Database 11g Release 1 及以上版本的一个新特性。它处理的是父 / 子对等分区的问题。也就是说,要以某种方式对子表分区,使得各个子表分区分别与一个你表分区存在一对一的关系。在某些情况下这很重要,例如假设有一个数据仓库,你希望保证一定数量的数据在线 (例如最近 5 年的 ORDER 信息),而且要确保相关联的子表数据(ORDER_LINE_ITEMS 数据) 也在线。在这个经典的例子中,ORDERS 表通常有一个 ORDER_DATE 列,所以可以很容易地按月分区,这也有利于保证最近 5 年的数据在线。随着时间推移,只需加载下一个朋的分区,并删除最老的分区。不过,考虑 ORDER_LINE_ITEMS 表时会看到存在一个问题。它没有 ORDER_DATE 列,而且 ORDER_LINE_ITEMS 表中根本没法有可以据以分区的列,因此无法帮助清除老信息或加载新信息。
过去,在引用分区出现之前,开发人员必须对数据逆规范化(denormalize),具体做法是:从父表 ORDERS 将 ORDER_DATE 属性复制到子表 ORDER_LINE_ITEMS。这会引入冗余数据,相应地带来数据冗余存在的一系列常见问题,比如存储开销增加、数据加载资源增加、级联更新问题(如果修改父表,还必须确保更新父表数据的所有副本),等等。另外,如果在数据库中启用了外键约束(而且确实应当启用外键约束),会发现无法截除或删除父表中原来的分区。例如,下面来创建传统的 ORDERS 和 ORDER_LINE_ITEMS 表。先看 ORDERS 表:
zx@ORCL>create table orders
  2  (
  3    order#      number primary key,
  4    order_date  date NOT NULL,
  5    data      varchar2(30)
  6  )
  7  enable row movement
  8  PARTITION BY RANGE (order_date)
  9  (
 10    PARTITION part_2016 VALUES LESS THAN (to_date(’01-01-2017′,’dd-mm-yyyy’)) ,
 11    PARTITION part_2017 VALUES LESS THAN (to_date(’01-01-2018′,’dd-mm-yyyy’)) 
 12  )
 13  /
 
Table created.
 
zx@ORCL>insert into orders values
  2  (1, to_date( ’01-jun-2016′, ‘dd-mon-yyyy’), ‘xxx’ );
 
1 row created.
 
zx@ORCL>insert into orders values
  2  (2, to_date( ’01-jun-2017′, ‘dd-mon-yyyy’), ‘xxx’ );
 
1 row created.
 
zx@ORCL>commit;
 
Commit complete.

现在来创建 ORDER_LINE_ITEMS 表,并插入一些数据指向 ORDERS 表:
zx@ORCL>create table order_line_items
  2  (
  3    order#      number,
  4    line#      number,
  5    order_date  date, — manually copied from ORDERS!
  6    data      varchar2(30),
  7    constraint c1_pk primary key(order#,line#),
  8    constraint c1_fk_p foreign key(order#) references orders
  9  )
 10  enable row movement
 11  PARTITION BY RANGE (order_date)
 12  (
 13    PARTITION part_2016 VALUES LESS THAN (to_date(’01-01-2017′,’dd-mm-yyyy’)) ,
 14    PARTITION part_2017 VALUES LESS THAN (to_date(’01-01-2018′,’dd-mm-yyyy’)) 
 15  )
 16  /
 
Table created.
 
zx@ORCL>insert into order_line_items values
  2  (1, 1, to_date( ’01-jun-2016′, ‘dd-mon-yyyy’), ‘yyy’ );
 
1 row created.
 
zx@ORCL>insert into order_line_items values
  2  (2, 1, to_date( ’01-jun-2017′, ‘dd-mon-yyyy’), ‘yyy’ );
 
1 row created.
 
zx@ORCL>commit;
 
Commit complete.

现在如果要删除包含 2016 年数据的 ORDER_LINE_ITEMS 分区,也可以删除对应 2016 年的 ORDERS 分区而不会违反引用完整性约束。尽管我们都很清楚这一点,但数据库并不知道:
zx@ORCL>alter table order_line_items drop partition part_2016;
 
Table altered.
 
zx@ORCL>alter table orders          drop partition part_2016;
alter table orders          drop partition part_2016
*
ERROR at line 1:
ORA-02266: unique/primary keys in table referenced by enabled foreign keys

所以,对数据逆规范化的做活很笨拙,会耗费资源,而且可能破坏数据的完整性。不仅如此,它还会妨碍管理分区表时经常需要做的一项工作:清除老信息。

下面来看引用分区。采用引用分区,子表会继承父表的分区机制,而不必对分区键逆规范化,而且更重要的是,它会让数据库了解这个子表与父表之间存在对等分区特点。也就是说,截除或删除生意人子表分区时,也能删除或截除父表分区。
要重新实现前面的例子,语法很简单,如下所示,这里将重用现胡的你表 ORDERS,只需要截除这个表:
zx@ORCL>drop table order_line_items cascade constraints;
 
Table dropped.
 
zx@ORCL>truncate table orders;
 
Table truncated.
 
zx@ORCL>insert into orders values
  2  (1, to_date( ’01-jun-2016′, ‘dd-mon-yyyy’), ‘xxx’ );
 
1 row created.
 
zx@ORCL>insert into orders values
  2  (2, to_date( ’01-jun-2017′, ‘dd-mon-yyyy’), ‘xxx’ );
 
1 row created.
 
zx@ORCL>commit;
 
Commit complete.

创建一个新的子表:
zx@ORCL>create table order_line_items
  2  (
  3    order#      number NOT NULL,
  4    line#      number NOT NULL,
  5    data      varchar2(30),
  6    constraint c1_pk primary key(order#,line#),
  7    constraint c1_fk_p foreign key(order#) references orders
  8  )
  9  enable row movement
 10  partition by reference(c1_fk_p)
 11  /
 
Table created.
 
zx@ORCL>insert into order_line_items values
  2  (1, 1, ‘yyy’);
 
1 row created.
 
zx@ORCL>insert into order_line_items values
  2  (2, 1, ‘yyy’);
 
1 row created.
 
zx@ORCL>commit;
 
Commit complete.

神奇之处就在 CREATE TABLE 语句的第 10 行。在这里,我们将区间分区语句替换为 PARTITION BY REFERENCE。
这允许我们指定要使用的外键约束,从而发现分区机制。在这里可以看到外键指向 ORDERS 表——数据库读取 ORDERS 表的结构,并发现它有两个分区。因此,子表会有两个分区。实际上,如果现在查询数据字典可以得到:
zx@ORCL>set linesize 200
zx@ORCL>col table for a20
zx@ORCL>col partition_name for a20
zx@ORCL>select table_name, partition_name
  2    from user_tab_partitions
  3  where table_name in (‘ORDERS’, ‘ORDER_LINE_ITEMS’)
  4  order by table_name, partition_name
  5  /
 
TABLE_NAME                                                                                PARTITION_NAME
—————————————————————————————— ——————–
ORDERS                                                                                    PART_2016
ORDERS                                                                                    PART_2017
ORDER_LINE_ITEMS                                                                          PART_2016
ORDER_LINE_ITEMS                                                                          PART_2017

可以看到两个表的结构完全相同。另外,由于数据库知道这两个表是相关联的,可以删除父表分区,并让它自动清除相关的子表分区(因为子表从父表继承而来,所以父表分区结构的任何调整都会向下级联传递到子表分区):
zx@ORCL>alter table orders drop partition part_2016 update global indexes;
 
Table altered.
 
zx@ORCL>select table_name, partition_name
  2    from user_tab_partitions
  3  where table_name in (‘ORDERS’, ‘ORDER_LINE_ITEMS’)
  4  order by table_name, partition_name
  5  /
 
TABLE_NAME                                                                                PARTITION_NAME
—————————————————————————————— ——————–
ORDERS                                                                                    PART_2017
ORDER_LINE_ITEMS                                                                          PART_2017

因此,之前不允许完成的 DROP 现在则是完全允许的,它会自动级联传递到子表。另外如果使用 ADD 增加一个分区:
zx@ORCL>alter table orders add partition
  2  part_2018 values less than
  3  (to_date( ’01-01-2019′, ‘dd-mm-yyyy’));
 
Table altered.
 
zx@ORCL>select table_name, partition_name
  2    from user_tab_partitions
  3  where table_name in (‘ORDERS’, ‘ORDER_LINE_ITEMS’)
  4  order by table_name, partition_name
  5  /
 
TABLE_NAME                                                                                PARTITION_NAME
—————————————————————————————— ——————–
ORDERS                                                                                    PART_2017
ORDERS                                                                                    PART_2018
ORDER_LINE_ITEMS                                                                          PART_2017
ORDER_LINE_ITEMS                                                                          PART_2018

可以看到,这个操作也会向下级联传递。父表与子表之间存在一种一对一的关系。

参考

Oracle Database 9i/10g/11g 编程艺术:深入数据库体系结构(第 2 版)PDF  http://www.linuxidc.com/Linux/2016-02/128078.htm

官方文档:http://docs.oracle.com/cd/E11882_01/server.112/e25523/partition.htm#CACIHDII

更多 Oracle 相关信息见Oracle 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=12

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-01/139883.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计5878字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中