万能数据库设计方法探索
更新:HHH   时间:2023-1-7


近日负责公司统一用户中心的数据库表结构设计,在工作过程中,诞生了一些另类的想法,特分享出来,期待大家拍砖。


思想的演化过程如下。


第一阶段:

将企业、机构、家庭等实体抽象为“组织”,Organization,简称 “O”,允许多级组织,通过parentId关联;

将部门等组织下属分支实体抽象为“部门”,Department,简称“D”,允许多级部门,通过parentId关联;

将自然人实体抽象为“自然人”,Human,简称“H”;

抽象出“账户”,Account,简称“A”;

抽象出“角色”,Role,简称“R”。

每一个组织允许拥有多个部门;每一个组织允许拥有多个自然人;每一个部门允许拥有多个自然人。

每一个组织、部门、自然人,都允许拥有多个账户。

账户可以共享多个角色。

第一阶段E-R关系如图

这是一个非常简单清晰的模型。

遗憾,真实世界不会如此简单。


第二阶段:

通过对产品业务的深入了解,需求变更为:

一个组织拥有多个部门,但同时一个部门可以从属于多个组织。(例:两个独立经营的连锁药店,共享同一个仓储部门。)

一个部门拥有多个自然人,但一个自然人可以从属于多个部门。(例:一个公司的总经理,兼职多个重要部门的部门经理。)

一个组织拥有多个自然人,但一个自然人可以从属于多个组织。(例:一个医生,可以多点执业。)

第二阶段E-R关系如图

现在还算是正常情况。


第三阶段:

新增一个简单的功能——邮政收货地址。

这是一个简单功能,但此次复杂之处在于:业务上,到底是“组织拥有收货地址?部门拥有收货地址?自然人拥有收货地址?还是账户拥有收货地址?各实体与收货地址,是一对一,还是一对多的关系?”这些问题,产品无法确定未来的功能扩展方向,只能回答“都有可能”。哈哈。。。

按照常规方法设计,为组织、部门、自然人、账户与收货地址之间,两两添加多对多关系表。关系表的数量开始膨胀,如同一个果园里,杂草数量比果蔬的数量都要多。。。

为了减少杂草数量,设计了一种抽象杂草:

添加实体(组织、部门、自然人、账户)与邮政地址的关系,由实体枚举code与实体id两个值,决定真实实体;由邮政收货地址Id,决定收货地址。

例如:

实体枚举code O, 实体id 1,邮政收货地址id 10,表示:id为1的某个组织,拥有id为10的某个收货地址。

实体枚举code H, 实体id 2,邮政收货地址id 20,表示:id为2的某个自然人,拥有id为20的某个收货地址。

实体枚举code A, 实体id 3,邮政收货地址id 30,表示:id为3的某个账户,拥有id为30的某个收货地址。

第三阶段E-R关系如图

第四阶段:

此时公司高层加入需求讨论,

A、要求对数据的控制颗粒度应该达到单条数据,并且可能要根据数据与周边任意实体的关系,进行权限控制,但是具体需求不定,要求做最大弹性设计。

B、追加资质管理、效期管理等功能,业务同样不知道未来的扩展方向在哪里,要求做最大弹性设计。

于是,抽象杂草的数量也开始膨胀起来。

针对需求A,设计了OneId表,将所有实体的Id在表中备份,未来一旦进行数据行级权限控制,通过OneId表进行关系扩展。

而为了让抽象杂草的数量不膨胀,设计了万用关系表,设计如下:

万用关系表
实体枚举code实体Id实体枚举code实体Id

举例

万用关系表
实体枚举code实体Id实体枚举code实体Id
O1H10
O1H11
H10A100
H10A101

上述数据,描述了

“Id为1的某个组织,拥有id为10、11的两个自然人”;

“Id为10的某个自然人,拥有id为100、101的两个账户”。


任何复杂的/未定的多对多关系,都可以用此万用关系表进行描述。


整个数据库设计最终版变化为:

注意:无论未来业务如何扩展,关系如何变化,仅需要扩展新的实体即可,不用再考虑与其他实体的关系,对历史设计不会产生任何冲击。


这是一种背离了所有现行数据库设计范式,简单万能的数据库设计方法,Universal DB Design Method,UDDM,简称犹大方法吧,感觉很贴切。


对上述设计方法,我的团队内部已没有足够的能力去评判正误,期待大家踊跃拍砖、共同探索。


返回关系型数据库教程...