Database design 如何在列上存储元数据

Database design 如何在列上存储元数据,database-design,normalization,entity-attribute-value,Database Design,Normalization,Entity Attribute Value,假设您正在收集即将上映的超级英雄电影的内幕信息,您的主电影表如下所示: Movie DirectorSource DirectorJournalist LeadingMaleSource LeadingMaleJournalist ... --------------------------------------------------------------------------------------- The Tick Yahoo Cameron

假设您正在收集即将上映的超级英雄电影的内幕信息,您的主电影表如下所示:

Movie    DirectorSource  DirectorJournalist  LeadingMaleSource  LeadingMaleJournalist ...
---------------------------------------------------------------------------------------
The Tick   Yahoo           Cameron           ...                ...
表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
这在一般情况下应该工作得很好,并且允许非常简单的查询以及行之间的比较

但是,您希望跟踪每个数据事实的来源,以及发现事实的记者的姓名。这似乎是一张类似这样的桌子:

Movie    DirectorSource  DirectorJournalist  LeadingMaleSource  LeadingMaleJournalist ...
---------------------------------------------------------------------------------------
The Tick   Yahoo           Cameron           ...                ...
表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
...
虽然它很容易捕获我们想要的元数据,但这使得查询更加困难。简单地获得一部电影的所有基本数据需要更多的时间。更具体地说,您必须在这里处理四行,以获得关于绿灯的四个重要信息,而在表1中,它是一个单独的、封装良好的行

所以我的问题是,考虑到我刚才描述的复杂性,并且因为我知道通常要避免EAV表,所以EAV仍然是最好的解决方案吗?似乎这是表示这些数据的唯一合理方式。我看到的唯一其他选择是将表1与另一个仅包含以下元数据的表结合使用:

Movie    DirectorSource  DirectorJournalist  LeadingMaleSource  LeadingMaleJournalist ...
---------------------------------------------------------------------------------------
The Tick   Yahoo           Cameron           ...                ...
表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
...
但这是非常危险的,因为如果有人将表1中的列名(如“Villain”更改为“Primary Villain”),表3中的行仍将简单地表示为“Villain”,因此相关数据将不幸地解耦。如果“attribute”列链接到另一个用作表1列枚举的表,则这可能会有所帮助。当然,DBA将负责维护该枚举表,以匹配表1的实际列。实际上,可以通过在SQLServer中使用包含表1中列名称的系统视图,而不是手动创建枚举表来进一步改进这一点。虽然我不确定您是否可以拥有涉及系统视图的关系

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

如果它只是一个元数据列(只有“源”而没有“记者”)——它仍然需要走EAV路线吗?你可以有“Director”、“Director\u Source”、“Leading Male”、“Leading Male\u Source”等栏目,但这很快就会变得难看。有没有更好的解决办法我没想到

如果我没有澄清任何一点,请发表评论,我会根据需要补充更多。哦,是的,我使用的电影数据是伪造的:)

编辑:为了简洁地重申我的主要问题,我希望有表1的简单性和真正的RDBMS设计,它确实很好地描述了电影条目,同时仍然以安全和可访问的方式存储属性上的元数据。这可能吗?还是EAV是唯一的方法

编辑2:在做了更多的web研究之后,我还没有找到一个关于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

我的回答似乎有点过于哲学化。请容忍我

我认为“源”栏不是主题数据,而是元数据。这实际上是关于我们如何知道其他一些数据的数据。这使得它成为关于数据的数据,这就是元数据

EAV造成问题的原因之一是它将数据和元数据混合在一行中。有时候,我自己故意这么做,作为实现我想要的结果的中间步骤。但我从未尝试过在我的可交付成果中混用数据和元数据


我知道为什么我从来没有这样做过,但我不能简明扼要地解释它。

因为没有其他人真正尝试过,所以我要回答我自己的问题。我敢肯定,像EAV这样的桌子确实是唯一的选择。要在每个列上存储元数据(在本例中是关于源和记者的),实际上是将每个列本身视为一个实体,这是EAV所允许的


您可以选择其他方法,比如为每个原始列添加第二列和第三列来存储数据,但这肯定会破坏一些基本的规范化规则,可能只会在以后给您带来痛苦。

Hmm。。。。我没有使用过这个,所以我不是根据经验(也就是说,如果它不起作用,请不要怪我),但表面上看,您可以存储“公共”数据,您知道这些数据将始终存在,就像在普通表中一样,以及可能会更改为XML的“元数据”。接下来的问题是如何很好地查询它,我认为您可能能够像前面所描述的那样进行查询

有趣的场景。你可以通过将你的实体视为第一类对象来绕过EAV贫民区;让我们称之为事实。这有助于你在这种情况下非常正交,因为每部电影都有完全相同的四个事实。您的EAV表可以是原始/正确的表,然后您可以有一个外部进程来挖掘该表,并将数据复制到正确的规范化形式(即第一个表)。通过这种方式,您可以获得所需的数据及其元数据,并且可以方便地查询电影信息,精确到挖掘过程运行的频率

我认为您确实需要一些“数据库外”的肌肉来确保数据保持有效,因为似乎没有任何I
MovieID | Movie Name | Director | LeadingMale | LeadingFemale | PrimaryVillain | etc
Table Movie
========================
MovieID   NUMBER, PrimaryKey
MovieName VARCHAR

Table MovieFact
========================
MovieID          NUMBER,  PrimaryKeyCol1
FactType         VARCHAR, PrimaryKeyCol2
FactValue        VARCHAR
FactSource       VARCHAR
FactJournalist   VARCHAR
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
...