元数据-模型-实例数据库设计的典型范式

元数据-模型-实例是一个很常见的设计成例——实际上,我觉得它应该属于解决一大类问题的设计模式的一种,在很多书里面也提到过这个东西。比如说在《面向模式的软件架构》系列里面,就提到过类似的设计模式。

这里主要讨论这种模式在数据库设计上的一些典型的做法,但是也局限于关系型数据库,对于非关系型数据库而言,设计也多有不同。在设计数据库的时候,主要分成模型表的设计和实例表的设计。

模型相关表设计

基础设计

我将模型定义为属性的集合。即一个模型通过模型所具有哪些属性来描述的,不同的属性又有不同的特征。

首先需要有一个模型表,我们暂时叫它Model。它的主要列都是描述模型自身的属性。举例来说:

模型表

比如第一条记录,其含义是有一个叫做“电脑”的模型,它适用于3C这个类目之下。

接下来是属性表(Attr):

属性表

属性表里面的记录是对属性自身的描述。举例来说,第一条记录的意思是有一个叫做memory的属性,其中文名字是内存,它的类型是数字——即实例里面该属性的取值应该是一个数字,Validator要求该属性的取值是大于0的,并且是必须具备的。也就是说,如果一个模型用到了该属性,那么任何一个实例,该属性都应该有取值,并且是大于0的。

之后,还需要一个表将模型和属性关联起来,其含义是这些模型是由这些属性组成的,而一个实例就是由这些属性的取值描述的。

关联表(Assn):

关联表

到这里,关于模型表的基本表结构就出来了。下面我们讨论一下扩展结构。

扩展设计

不论是模型表,还是属性表,在复杂业务的时候,都需要引入一些扩展结构。

首先是模型表,在Model里面,涉及的都是所有Model都需要有的公共属性——始终记得这些属性是对模型自身的描述而与实例无关。而对于一些模型来说,会有一些扩展的内容。举个例子来说,电脑这个Model要有一个Account的属性,表达仅有这个账号才能创建电脑模型的实例;而相应的汽车这个Model具有一个City的属性,表达汽车这个Model只能在这些城市使用。

于是我们可以轻易设计一个ModelExt表,用于表达这种关于模型自身的扩展属性:

ModelExt

同样的道理,不同的属性也会有不同的扩展内容。举例来说,轮子品牌是一个枚举量,即轮子品牌的取值是有限个预先定义的值中的一个;屏幕尺寸有一个单位的属性,即屏幕尺寸应该是XXX英寸。那么也可以通过一个属性表的扩展来实现,AttrExt:

AttrExt

连续的Attr只是为了强调这张表的属性,是模型属性的属性,也就是attr's attr。

这里非常重要的一点是:模型表,包括模型扩展表,存储的数据是对模型自身的描述,是将模型看成一个整体之后的描述;属性表,属性扩展表,是对组成这个模型的各个属性的描述

实例相关表设计

基础设计

实例,是指模型的一个具体化。也就是说,模型的组成属性的各个取值能够构成一个实例。比如说,对手机模型进行实例化,我们能够得到iphone8,小米红米手机。

实例表(Instance)是第一个表:

Instance

这张表可以简单成这样,也就是只有一列ID属性和一列ModelID。后续我们会在扩展结构里面讨论这张表放置一些别的列的设计。

属性取值表AttrValue:

AttrValue

比如,第一列的意思就是有一台(款)电脑,内存是16G,屏幕尺寸是45英寸。

扩展设计

第一种扩展设计是扩展实例表:

Instance

注意的是,这种扩展方式,相当于默认任何模型都有两个组成属性,name和desc。其等价于:

a. 在Attr表中增加两个字段

Attr

b. 同时在Assn表中增加上相应的关联:

Assn

c. 在AttrValue里面加上name和desc的取值:

AttrValue

不过大多数的时候,设计都是直接在Instance表里放置模型基础属性的取值,而放弃其等价形式。所带来的后果就是当获取模型的全部属性(含自身描述属性,组成属性)时候将会缺少这一部分基础属性。


第二种变种是,在Instance实例表里面不使用ModelID,而是使用Model Name。这是可以的——因为这能够带来可读性的上升,但是要注意的就是,Model Name应该保证全局唯一那么在Model表里面,给Name列加上唯一索引,是最好的做法了。


有些人喜欢在AttrValue里面,用AssnID取代AttrID,我对此持保留意见。我认为纯粹的从语义上来说,应该使用的是AttrID,即表达在该属性下的取值。如果能够保证在Model下AttrName是唯一的,那么AttrValue里面的AttrID可以用AttrName来取代,以换取可读性的提高。

使用NoSQL

从前面的设计可以看到,我们采用了大量的key-value形式的存储结构(其标准名称应该是EAV,即Entity-Attribute-Value)。它的几个缺陷是无法在建索引,无法执行聚合运算等,查询效率低等。实际上,一种可以考虑的改进是,采用NoSQL。实际上NoSQL也不一定能够解决EAV存在的问题,只是它们看上去更加合适一点。

首要推荐的NoSQL存储方式是采用列族存储。使用列族存储的数据库,可以将表设计成宽表,成百上千个列都可以,但是每一行数据都只对其中某几个列有取值;

其次推荐的是文件式存储,如MongoDB。这一类的存储,可以将模型和实例的数据写成一种很适合人类阅读的文本形式,而后进行存储。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容