微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Oracle11g新特性:引用分区(reference partitioning)

引用分区(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>createtableorders
2(
3order#numberprimarykey,4order_datedateNOTNULL,5datavarchar2(30)
6)
7enablerowmovement
8PARTITIONBYRANGE(order_date)
9(
10PARTITIONpart_2016VALUESLEsstHAN(to_date('01-01-2017','dd-mm-yyyy')),11PARTITIONpart_2017VALUESLEsstHAN(to_date('01-01-2018','dd-mm-yyyy'))
12)
13/

Tablecreated.

zx@ORCL>insertintoordersvalues
2(1,to_date('01-jun-2016','dd-mon-yyyy'),'xxx');

1rowcreated.

zx@ORCL>insertintoordersvalues
2(2,to_date('01-jun-2017','xxx');

1rowcreated.

zx@ORCL>commit;

Commitcomplete.

现在来创建ORDER_LINE_ITEMS表,并插入一些数据指向ORDERS表:

zx@ORCL>createtableorder_line_items
2(
3order#number,4line#number,5order_datedate,--manuallycopiedfromORDERS!
6datavarchar2(30),7constraintc1_pkprimarykey(order#,line#),8constraintc1_fk_pforeignkey(order#)referencesorders
9)
10enablerowmovement
11PARTITIONBYRANGE(order_date)
12(
13PARTITIONpart_2016VALUESLEsstHAN(to_date('01-01-2017',14PARTITIONpart_2017VALUESLEsstHAN(to_date('01-01-2018','dd-mm-yyyy'))
15)
16/

Tablecreated.

zx@ORCL>insertintoorder_line_itemsvalues
2(1,1,'yyy');

1rowcreated.

zx@ORCL>insertintoorder_line_itemsvalues
2(2,'yyy');

1rowcreated.

zx@ORCL>commit;

Commitcomplete.

现在如果要删除包含2016年数据的ORDER_LINE_ITEMS分区,也可以删除对应2016年的ORDERS分区而不会违反引用完整性约束。尽管我们都很清楚这一点,但数据库并不知道:

zx@ORCL>altertableorder_line_itemsdroppartitionpart_2016;

Tablealtered.

zx@ORCL>altertableordersdroppartitionpart_2016;
altertableordersdroppartitionpart_2016
*
ERRORatline1:
ORA-02266:unique/primarykeysintablereferencedbyenabledforeignkeys

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

下面来看引用分区。采用引用分区,子表会继承父表的分区机制,而不必对分区键逆规范化,而且更重要的是,它会让数据库了解这个子表与父表之间存在对等分区特点。也就是说,截除或删除生意人子表分区时,也能删除或截除父表分区。

要重新实现前面的例子,语法很简单,如下所示,这里将重用现胡的你表ORDERS,只需要截除这个表:

zx@ORCL>droptableorder_line_itemscascadeconstraints;

Tabledropped.

zx@ORCL>truncatetableorders;

Tabletruncated.

zx@ORCL>insertintoordersvalues
2(1,'xxx');

1rowcreated.

zx@ORCL>commit;

Commitcomplete.

创建一个新的子表:

zx@ORCL>createtableorder_line_items
2(
3order#numberNOTNULL,4line#numberNOTNULL,5datavarchar2(30),6constraintc1_pkprimarykey(order#,7constraintc1_fk_pforeignkey(order#)referencesorders
8)
9enablerowmovement
10partitionbyreference(c1_fk_p)
11/

Tablecreated.

zx@ORCL>insertintoorder_line_itemsvalues
2(1,'yyy');

1rowcreated.

zx@ORCL>commit;

Commitcomplete.

神奇之处就在CREATE TABLE语句的第10行。在这里,我们将区间分区语句替换为PARTITION BY REFERENCE。

这允许我们指定要使用的外键约束,从而发现分区机制。在这里可以看到外键指向ORDERS表――数据库读取ORDERS表的结构,并发现它有两个分区。因此,子表会有两个分区。实际上,如果现在查询数据字典可以得到:

zx@ORCL>setlinesize200
zx@ORCL>coltablefora20
zx@ORCL>colpartition_namefora20
zx@ORCL>selecttable_name,partition_name
2fromuser_tab_partitions
3wheretable_namein('ORDERS','ORDER_LINE_ITEMS')
4orderbytable_name,partition_name
5/

TABLE_NAMEPARTITION_NAME
--------------------------------------------------------------------------------------------------------------
ORDERSPART_2016
ORDERSPART_2017
ORDER_LINE_ITEMSPART_2016
ORDER_LINE_ITEMSPART_2017

可以看到两个表的结构完全相同。另外,由于数据库知道这两个表是相关联的,可以删除父表分区,并让它自动清除相关的子表分区(因为子表从父表继承而来,所以父表分区结构的任何调整都会向下级联传递到子表分区):

zx@ORCL>altertableordersdroppartitionpart_2016updateglobalindexes;

Tablealtered.

zx@ORCL>selecttable_name,partition_name
5/

TABLE_NAMEPARTITION_NAME
--------------------------------------------------------------------------------------------------------------
ORDERSPART_2017
ORDER_LINE_ITEMSPART_2017

因此,之前不允许完成的DROP现在则是完全允许的,它会自动级联传递到子表。另外如果使用ADD增加一个分区:

zx@ORCL>altertableordersaddpartition
2part_2018valueslessthan
3(to_date('01-01-2019','dd-mm-yyyy'));

Tablealtered.

zx@ORCL>selecttable_name,partition_name
5/

TABLE_NAMEPARTITION_NAME
--------------------------------------------------------------------------------------------------------------
ORDERSPART_2017
ORDERSPART_2018
ORDER_LINE_ITEMSPART_2017
ORDER_LINE_ITEMSPART_2018

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


参考《ORACLE DATABASE 9I10G11G编程艺术》

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

原文地址:https://www.jb51.cc/oracle/210719.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐