如何在列上存储元数据

Joe*_*ool 11 database-design normalization entity-attribute-value

假设您正在收集有关即将发布的超级英雄电影的内幕信息,您的主电影表看起来像这样:

表格1

Title              Director   Leading Male      Leading Female    Villain
--------------------------------------------------------------------------
Green Lantern      Kubrick    Robert Redford     Miley Cyrus     Hugh Grant  
The Tick          Mel Gibson  Kevin Sorbo        Linda Hunt    Anthony Hopkins
Run Code Online (Sandbox Code Playgroud)

这通常可以很好地工作,并允许非常简单的查询以及行之间的比较.

但是,您希望跟踪每个数据事实的来源,以及发现该事实的记者的姓名.这似乎暗示了某种类似这样的EAV表:

表2

Movie             Attribute            Value          Source          Journalist
----------------------------------------------------------------------------------
Green Lantern      Director           Kubrick         CHUD              Sarah
Green Lantern    Leading Male      Robert Redford     CHUD              James
Green Lantern   Leading Female      Miley Cyrus    Dark Horizons        James
Green Lantern      Villain           Hugh Grant       CHUD              Sarah
The Tick           Director          Mel Gibson       Yahoo            Cameron
...
Run Code Online (Sandbox Code Playgroud)

虽然它可以轻松捕获我们想要的元数据,但却更难以进行查询.简单地获取单个电影的所有基本数据需要更多.更具体地说,你必须在这里处理四行以获得绿灯侠上的四个重要信息,而在表1中它是一个单独的,封装良好的行.

所以我的问题是,鉴于我刚才描述的复杂情况,并且因为我知道EAV表一般要避免,EAV仍然是最好的解决方案吗?它似乎是表示此数据的唯一合理方式.我看到的唯一另一种选择是将表1与另一个包含元数据的表一起使用:

表3

Movie             Attribute            Source          Journalist
----------------------------------------------------------------------------------
Green Lantern      Director             CHUD              Sarah
Green Lantern    Leading Male           CHUD              James
Green Lantern   Leading Female      Dark Horizons         James
Green Lantern      Villain              CHUD              Sarah
The Tick           Director             Yahoo            Cameron
...
Run Code Online (Sandbox Code Playgroud)

但这是非常危险的,因为如果有人将表1中的列名称更改为"小恶棍",那么表3中的行仍然会简单地说"恶棍",因此相关数据将很遗憾地解耦.如果"属性"列链接到另一个用作表1列的枚举的表,则可以帮助这一点.当然,DBA将负责维护此枚举表以匹配表1的实际列.实际上可以通过手动创建枚举表来进一步改进这一点,在SQL Server中使用系统视图,其中包含表1中列的名称.虽然我不确定您是否可以拥有涉及的关系系统视图.

你有什么建议?EAV是唯一的出路吗?

如果它只是一个元数据列(只有"源"而没有"记者"),那么它仍然需要走EAV路线吗?您可以拥有"Director","Director_Source","Leading Male","Leading Male_Source"等列,但这很快就会变得难看.我有没有想到更好的解决方案?

如果我没有澄清任何一点请评论,我会在必要时添加更多.哦是的,我用的电影数据是捏造的:)

编辑:简要地重述我的主要问题,我希望得到表1的简单性和真正的RDBMS设计,它真正描述了一个电影条目,同时仍然以安全和可访问的方式将元数据存储在属性上.这可能吗?或者EAV是唯一的方式?

编辑2:在做了更多的网络研究之后,我还没有找到关于EAV的讨论,这些讨论的核心是在列上存储元数据的愿望.实现EAV的主要原因几乎总是动态且不可预测的列,在我的示例中并非如此.在我的例子中,总有相同的四列:导演,男主角,女主角,反派.但是,我想存储关于每一行的每列的某些事实(来源和记者).EAV会促进这一点,但我想避免诉诸于此.

更新

使用表2设计除了将"Movie"列重命名为"Name"并调用整个表"Movie"之外,这里是SQL Server 2008中的枢轴操作以返回表1:

SELECT Name, [Director], [Leading Male], [Leading Female], [Villain]
FROM (Select Name, Attribute, Value FROM Movie) as src
PIVOT
(
Max(Value)
FOR Attribute IN ([Director], [Leading Male], [Leading Female], [Villain])
)  AS PivotTable
Run Code Online (Sandbox Code Playgroud)

LBu*_*kin 6

您可以在设计中更改您认为是事实值的内容 ......您的数据模型中的事实似乎可以表示为以下N元组:

Movie | FactType | FactValue | FactSource | FactJournalist
Run Code Online (Sandbox Code Playgroud)

下表结构应该支持您想要的数据模型,并且可以相对容易地编制索引和连接.您还可以创建一个视图,仅显示事实值和事实类型,以便您可以创建以下透视图:

MovieID | Movie Name | Director | LeadingMale | LeadingFemale | PrimaryVillain | etc
Run Code Online (Sandbox Code Playgroud)

有趣的是,您可以认为这是将EAV模型完全应用于数据的逻辑扩展,并将单个电影(具有导演,导演,恶棍等的直观归属)分解为一个旋转结构,其中属性集中于源而是信息.

建议的数据模型的好处是:

  • 它被很好地规范化了(尽管你应该将FactType字段规范化为参考表以获得完整性)
  • 可以创建一个视图,将事实类型有效地转换为表格结构
  • 它是相对可扩展的,并允许数据库强制引用完整性和(如果需要)基数约束
  • MovieFact表可以被子类化以支持不同类型的电影事实,而不仅仅是那些简单的文本字段
  • 对数据的简单查询相对有效

数据模型的一些缺点是:

  • 复合条件查询更难(但并非不可能)编写(例如查找Director为A且Leading Male为B等的所有电影......)
  • 该模型比较传统的方法或涉及EAV结构的方法稍微不那么明显
  • 插入和更新有点棘手,因为更新多个事实需要更新多行,而不是多列

我将电影数据升级到一个级别以规范化结构,你可以将电影名称下移到MovieFact结构中以保持一致性(因为对于某些电影我可以想象,即使这样,你可能想要跟踪源信息的名称) .

Table Movie
========================
MovieID   NUMBER, PrimaryKey
MovieName VARCHAR

Table MovieFact
========================
MovieID          NUMBER,  PrimaryKeyCol1
FactType         VARCHAR, PrimaryKeyCol2
FactValue        VARCHAR
FactSource       VARCHAR
FactJournalist   VARCHAR
Run Code Online (Sandbox Code Playgroud)

您的虚构电影数据将如下所示:

Movie Table
====================================================================================
MovieID  MovieName
====================================================================================
1        Green Lantern
2        The Tick

MovieFact Table
====================================================================================
MovieID  FactType       FactValue         FactSource       FactJournalist
====================================================================================
1        Director       Kubrick           CHUD             Sarah
1        Leading Male   Robert Redford    CHUD             James
1        Leading Female Miley Cyrus       Dark Horizons    James
1        Villain        Hugh Grant        CHUD             Sarah
2        Director       Mel Gibson        Yahoo            Cameron
2        Leading Male   John Lambert      Yahoo            Erica
...
Run Code Online (Sandbox Code Playgroud)