8.2.?继承表特性

8.2.1. 概述
8.2.2. 详细功能
8.2.3. 限制条件
8.2.4. 处理流程
8.2.5. 修改继承表
8.2.6. 注意事项
8.2.7. 示例

8.2.1.?概述

继承表是拥有父表角色或子表角色的表,系统表ux_inherit保存所有的继承关系,如果某个表的OID在字段ux_inherit.inhrelid出现,那么它拥有“子表”角色,如果表OID在字段ux_inherit.inhparent出现,则拥有 “父表”角色。两种情形中的劝拿庞蜗菲教ㄗ⒉嵬锯一种,都称该表是一个“继承表”。

8.2.2.?详细功能

继承作为UXDB使用者的一种有用工具,具备若干特殊的性质。继承表存在两种角色:父表和子表,两者之间是多对多的关系,也就是说,一个父表可能存在多个子表,反过来,一个子表可能存在不止一个父表。继承表的性质具体体现在:

  1. 数据结构的继承

    一个表可能存在零个或多个父表,子表继承它的所有父表的所有列,劝拿庞蜗菲教ㄗ⒉嵬净父表数据结构的变化自动传播到子表,这里的数据结构变化包含增加或删除列,修改列的数据类型等。子表可以包含自定义的列,这些自定义的列是子表区别于父表的特性部分。OID类型的系统字段tableoid能标识当前列的真实来源。如果子表包含与父表列名字相同,数据类型也相同的列,这些列与父表列“合并”,子表只存在一个这样的列。

  2. check约束、NOT NULL约束及DEFAULT值的继承

    子表自动继承父表的所有check约束,NOT NULL约束,及DEFAULT值。如果子表与父表包含相同的列,子表列上的check约束,NOT NULL约束和DEFAULT值必须与父表完全相同,否则子表的列不能与父表列“合并”。

  3. 查询、更新和删除父表

    默认情况下,查询,更新和删除父表引用了父表的行以及它的所有后代的所有行。如果仅查询父表中符合条件的元组,需要明确指定关键字ONLY。

  4. 继承关系的创建和删除

    继承关系有两种创建方式,一种是创建子表时通过INHERITS子句指定父表,另一种是对于已存在的两个表,通过ALTER TABLE … INHERIT语法建立两者之间的继承关系。对于第二种方式,子表中必须已包含与父表具有相同名字,相同数据类型,相同DEFAULT值,相同NOT NULL约束的列,另外,如果父表包含CHECK约束,子表也必须包含具有相同名字和表达式的CHECK约束。而删除继承关系使用语法ALTER TABLE … NO INHERIT。

UXMPP支持对表分片,表中数据被分布存储在多个worker节点。目前UXMPP不支持对继承层次中的表进行分片(partition表除外)。另外,UXMPP无法把分片表作为子表或父表。结合继承表性质,UXMPP支持继承表的以下功能。

表?8.2.?继承表功能

一级功能二级功能
分片对于已存在继承关系的表,允许分片存储
修改对于分片表,支持将其设置为其它表的父表或者子表
父表数据结构的修改(增加或删除列,修改列的类型),应传播到worker节点的子表分片。
父表check/not null/default约束的增加或删除,传播到worker节点的子表分片
查询select的返回结果包含子表中符合条件的元组
select only只包含父表中符合条件的元组
更新update传播到子表分片
update only只修改父表中符合条件的元组
删除delete传播到子表
delete only只删除父表中符合条件的元组

8.2.3.?限制条件

为了使父表分片和子表分片能一一对应,uxmpp继承表分片时,必须满足以下约束条件:

  • 分片函数

    分片函数应使用函数create_distributed_table。UXMPP创建分片表的函数有两个:create_distributed_table和master_create_distributed_table。第二个函数已被废弃,它仅向系统表ux_dist_partition新增一条记录,并没有真正创建表的各个分片,因此不能使用该函数对继承表分片。另外,目前暂不支持将继承表创建为参考表,以后可能支持。

  • 分片方法

    分片方法必须是hash。函数create_distributed_table接受分片方法作为第三个参数,支持的分片方法包括hash,append和range。由于append和range方法并不真正创建分片,因此,继承表必须使用hash分片。

  • 复制因子

    为了简化问题,暂时规定继承表分片时复制因子必须1,每个分片都只有一份。

  • worker节点

    父表分片和子表分片所在的worker节点必须完全相同。不能父表分片分布在节点1,2,而子表分片分布在节点2,3。这一点也是为了保证每个子表分片所在的worker节点存在一个父表分片。

8.2.4.?处理流程

通过改造函数create_distributed_table,以支持继承表分片。由于继承表分片必须满足若干条件,所以定义函数CheckInheritedTable实施必要的检查。

表?8.3.?CheckInheritedTable函数

APICheckInheritedTable
目的检查继承表,如果不满足分片限制,报错
参数参数描述
relationId表的OID
relationId表的OID
distributionColumn分片列
distributionMethod分片方法
返回值

表?8.4.?checkIfTableSameDistributed函数

APIcheckIfTableSameDistributed
目的检查已存在的分片表是否与待分片表使用相同的复制因子,分片数和相同的worker节点,如果不是,提示错误。
参数参数描述
existingRelationId已分片表的OID
isParentexistingRelationId是否是父表
oDistributedRelationId待分片表的OID
shardcount待分片表的分片数
replicationfactor待分片表使用的复制因子
workerNodes待分片表的各个分片依次存储在哪些worker
返回值

8.2.5.?修改继承表

修改继承表涉及三部分功能:修改继承关系的传播、数据定义的传播、check/not null约束及default的传播。

8.2.5.1.?修改继承关系

修改继承关系的语法是ALTER TABLE c INHERIT/NO INHERIT p …。UXMPP主要考虑当c和p中至少有一个表是哈希分片表。对于c和p均是本地表的情形,不需要特殊处理,直接交给UXDB的规划器处理就足够了。

8.2.5.2.?数据定义/CHECK约束/NOT NULL约束/DEFAULT

当父表操作涉及以下几方面时,传播到子表及子表的各个分片。

  • 增加/删除列

  • 修改列的数据类型

  • 增加/删除可继承的CHECK约束

  • 增加/删除NOT NULL约束

  • 增加/删除DEFAULT值

  • 重命名列

  • 重命名可继承的CHECK约束

最后两项重命名操作对应于UXDB的语法ALTER TABLE … RENAME [COLUMN]…和ALTER TABLE … RENAME CONSTRAINT…,计划节点的类型是T_RenameStmt。前几种操作的计划节点类型是T_AlterTableStmt。

如果父表和子表均是分片表,worker节点记录了父表分片和子表分片的继承关系。当master节点修改父表的数据定义或约束时,父表分片的数据定义或约束相应地发生变化,进而传播到worker节点的子表分片。当父表或子表存在一个本地表时,由于本地表没有分片,worker节点无法记录分片间的继承关系,这种情况下父表数据定义及约束的修改无法在worker节点的分片之间传播,因此,当分片的父表有一个本地表作为孩子,或者本地的父表有一个分片表作为孩子时,必须限制用户修改父表的数据定义及约束。考虑到对多继承的支持,上述条件进而修正为,当分片的父表有一个本地表后代,或者本地的父表有一个分片表后代时,必须限制用户修改父表的数据定义及约束。

8.2.5.3.?查询/更新/删除继承表

查询,更新和删除继承表,主要涉及几方面的功能:

  1. 如果当前表是分片表,存在至少一个本地表后代,或者当前表是本地表,存在至少一个分片表后代,不允许对表进行查询,更新和删除。这是因为查询正确性依赖于worker节点上记录的父表分片与子表分片的继承关系,而这两种情况下,worker节点并没有保存分片的继承关系。

  2. 对于继承层次是均是分片表的情形,SELECT/UPDTAE/DELETE应当能够成功。

  3. 对于继承层次是均是分片表的情形,SELECT ONLY/UPDTAE ONLY/DELETE ONLY应当只引用父表元组。

8.2.6.?注意事项

如果父表是本地表,且存在分片表后代,那么select/update/delete目前仍是成功的,预期结果是提示用户该SQL查询不支持。

在根据Query结构恢复查询字符串时,一些不需要ONLY关键字的查询目标之前有多余的ONLY关键字。这些不影响查询结果,但其实是多余的。

允许复制因子大于1,允许参考表成为继承表。

8.2.7.?示例

8.2.7.1.?环境部署

表?8.5.?机器及相关信息

机器身份IP addressPort数据库
MasterCoordinator192.168.5.2115432uxdb
Worker001Worker192.168.5.2145432uxdb
Worker002Worker192.168.5.2155432uxdb

8.2.7.2.?创建继承关系

  • 方法一:创建子表时通过INHERITS语句指定父表,建立继承关系。

    1. 设置复制因子。

      set uxmpp.shard_replication_factor to 1; 
    2. 创建两个本地表,并将其分片,其中parent是child的父表。

      create table parent(no int default 18, name text not null check(name is not null));
      select create_distributed_table('parent', 'no');
      create table child(hobbies text) inherits (parent);
      select create_distributed_table('child', 'hobbies');
    3. 查看子表分片的表结构。

      select  a.shardid as shardid, a.nodename as nodename, a.nodeport as nodeport 
      				from ux_dist_shard_placement a, ux_dist_shard b 
      				where a.shardid = b.shardid and b.logicalrelid = 'child'::regclass order by a.shardid limit 1;				
      \gset
      \c - - :nodename :nodeport
      \d child_:shardid

      可看到子表分片继承了父表分片的表结构,默认值,not null,check约束等。

    4. 登录父分片表所在的worker通过\d + 父分片表名,查看结果。

  • 方法二:通过ALTER TABLE ... INHERIT语句建立两张表之间的继承关系;这种方式子表中必须包含与父表具有相同名字,相同数据类型,相同NOT NULL约束的列,另外,如果父表包含CHECK约束,子表也必须包含具有相同名字和表达式的CHECK约束。

    1. 创建两个本地表,并将其分片。其中 liu_bei是liu_shan的父表。

      create table liu_bei(no int , name text);
      create table liu_shan(no int , name text , oname varchar(64));
      select create_distributed_table('liu_shan', 'oname');
      alter  table  liu_shan  inherit  liu_bei;
      select create_distributed_table('liu_bei', 'no'); 
    2. 查看子表分片的表结构。

      select  a.shardid as shardid, a.nodename as nodename, a.nodeport as nodeport 
      				from ux_dist_shard_placement a, ux_dist_shard b
      				where a.shardid = b.shardid and b.logicalrelid = 'liu_shan'::regclass order by a.shardid limit 1;	
      \gset
      \c - - :nodename :nodeport
      \d  liu_shan_:shardid
    3. 登录父分片表所在的worker通过\d + 父分片表名,查看结果。

    4. 测试建立继承关系时,对几种约束的要求。

      create table sun_jian( name text not null check(name is not null));
      create table sun_ce( name text not null );
      create table sun_quan( name text );

      需要有相同的“not null”、“check”。

      create table cao_cao(age int default 18);
      create table cao_pi(age_ int default 18);
      create table cao_zhi(age smallint default 18);
      create table cao_zhang(age int);

      需要有相同的属性名、数据类型,但“default”可不一致。

8.2.7.3.?删除继承关系

  1. 在ux_inherit系统表中查询所有的继承关系。

    select inhrelid::regclass, inhparent::regclass from ux_inherits;
  2. 通过命令删除关系。

    alter table worker_1 no inherit person;
  3. 在worker查看ux_inherit系统表中所有的继承关系。

    select inhrelid::regclass, inhparent::regclass from ux_inherits;
XML 地图 | Sitemap 地图