具有多列的单个固定表与灵活的抽象表

Moa*_*oak 27 mysql sql database database-design data-modeling

我想知道你是否有一个网站上有十几种不同类型的列表(商店,餐馆,俱乐部,酒店,活动)需要不同的字段,是否有一个好处,创建一个表定义如下所示的列
示例:

shop_id | name | X | Y | city | district | area | metro | station | address | phone | email | website | opening_hours
Run Code Online (Sandbox Code Playgroud)

或者更类似于此的抽象方法:

object_id | name        
---------------
1         | Messy Joe's  
2         | Bate's Motel 

type_id | name
---------------
1       | hotel
2       | restaurant


object_id | type_id
---------------
1         | 2
2         | 1

field_id | name           | field_type
---------------
1        | address        | text
2        | opening_hours  | date 
3        | speciality     | text

type_id | field_id
---------------
1       | 1
1       | 2
2       | 1
2       | 3

object_id | field_id | value
1         | 1        | 1st street....
1         | 3        | English Cuisine
Run Code Online (Sandbox Code Playgroud)

当然,如果值是预定义的,它可以更抽象(例如:专业可以有自己的列表)

如果我采用抽象方法,它可以非常灵活,但是对于大量连接,查询会更复杂.但我不知道这是否会影响性能,执行这些"更复杂"的查询.

我很想知道这两种方法的优缺点是什么.我可以想象一下自己,但我没有经验证实这一点.

Per*_*DBA 81

我们进行合理的讨论之前,需要澄清和解决某些问题.

先决条件

  1. 标签
    在需要精确度的专业中,重要的是我们使用精确的标签,以避免混淆,以便我们可以在不必使用冗长的描述和限定符的情况下进行通信.
    .
    什么你已经张贴FixedTables,是Unnormalised.很公平,它可能是第三范式的尝试,但事实上它是一个平面文件,Unnormalised(不是"非规范化").你发布的AbstractTables确实是实体 - 属性 - 值,这几乎是,但不完全是,第六范式,因此比3NF更规范化.当然,假设它正确完成.

    • Unnormalised平面文件不是"非规范化".它充满了重复(没有采取任何措施来删除重复的组和重复的列或解决依赖关系)和Null,它在很多方面都是一种性能损失,并且阻止了并发性.

    • 为了被Denormlaised,它必须首先被归一化,然后归一化有一些很好的理由.由于它首先没有标准化,因此不能进行非规范化.它只是非标准化.

    • 它不能说是"为了表现"而非规范化,因为它是一种表现能力,它与性能截然相反.嗯,他们需要一个缺乏正式设计的理由],而"为了表现"就是这样.即使是最小的正式审查也暴露了虚假陈述(但很少有人可以提供,所以它仍然是隐藏的,直到他们得到一个局外人来解决,你猜对了,大规模的性能问题).

    • 归一化结构的性能远远优于非归一化结构.更正规化的结构(EAV/6NF)比不太正常化的结构(3NF/5NF)表现更好.

    • 我同意OMG小马的主旨,但不同意他们的标签和定义

    • 而不是说' 不要'反规范化"除非你必须',我说,'忠实地正常化,期间''如果存在性能问题,你没有正确地正常化'.
      .
  2. Wiki
    正常表格和规范化的条目是一个完整的笑话.具体来说,定义不正确; 他们混淆了普通形式; 他们对标准化的过程毫无头绪; 并且它们对于很久以前被揭穿的荒谬或可疑的NF给予同等重视.结果是,Wiki增加了一个已经混乱且很少被理解的主题.所以不要浪费你的时间.
    .
    但是,为了取得进展,没有那个参考构成障碍,让我这样说.

    • 3NF的定义是稳定的,并没有改变.
    • 3NF和5NF之间的NF存在很多混淆.事实是,这是一个在过去15年中取得进步的领域; 许多组织,学者以及他们的产品都有局限性的供应商,他们跳出来创建一个新的"普通形式"来验证他们的产品.所有服务商业利益和学术上不健全.3NF处于原始未被篡改的状态,旨在保证某些属性.
    • 总和是,5NF是今天,3NF打算在15年前,你可以跳过商业戏弄和12个左右的"特殊"(商业和伪学术)NF之间,其中一些是在Wiki中确定,甚至是在令人困惑的条款中.
      .
  3. 由于您已经能够在帖子中理解和实施EAV,因此您可以毫无疑问地理解以下内容.当然,真正的关系模型是先决条件,强键等等.第五范式是,因为我们正在跳过第四:

    • 第三范式
      • 以简单明确的术语表示,每个表中的每个非键列与表的主键具有1 :: 1的关系,
      • 而没有其他非关键列
    • 零数据重复(结果,如果正常化正在努力进行;不仅仅通过智能或经验实现,或者通过努力实现正式流程的目标)
    • 无更新异常(当您在某处更新列时,您不必更新位于其他位置的同一列;该列存在于一个且仅存在一个位置).
      .
  4. 第六范式当然是第五范式,加上:

    • 消除缺失的数据(列).这是Null问题(也称为处理缺失值)的一个真正的解决方案,结果是没有Null的数据库.(它可以在标准和Null替代品的5NF下完成,但这不是最佳的.)如何解释和显示缺失值是另一个故事.
      .
  5. EAV vs Sixth Normal Form
    我写的所有数据库,除了一个,都是纯5NF.我曾经使用过(管理,修复,增强)几个EAV数据库,我已经实现了一个真正的6NF数据库.EAV是6NF的松散实现,通常由那些没有很好地掌握归一化和NF的人来完成,但是他们可以看到EAV的价值,并且需要灵活性.你是一个很好的例子.区别在于:因为它是松散的,并且因为实现者没有忠实的引用(6NF),所以他们只实现了他们需要的东西,并且他们用代码写出来; 最终成为一个不一致的模型.
    .
    然而,纯粹的6NF实现确实具有纯粹的学术参考点,因此它通常更紧凑,更一致.通常,这会显示两个可见元素:
    • 6NF有一个包含元数据的目录,一切都是在元数据中定义的,而不是代码.EAV没有一个,一切都在代码中(实现者跟踪对象和属性).显然,目录可以简化列的添加,导航,并允许形成实用程序.
    • 理解为6NF,为Null问题提供真正的解决方案.EAV实施者,因为他们缺少6NF上下文,处理代码中丢失的数据,不一致或更糟,允许数据库中的Null.6NF实现者不允许Null,并且一致且优雅地处理丢失的数据,而不需要代码构造(对于Null处理;当然,您仍然必须编写缺失数据的代码).
      .
      例如.对于带有目录的6NF数据库,我有一组proc将[重新]生成执行所有SELECT所需的SQL,并且我为所有用户提供5NF的视图,因此他们不需要知道或理解底层的6NF结构.他们被赶出了目录.因此,变更很容易并且自动化.由于缺少目录,EAV类型手动执行此操作.

现在,我们可以开始了

讨论

"当然,如果价值是预定义的,那么它可能会更抽象(例如:专业可能有自己的清单)"

当然.但是不要太"抽象".保持一致性并以与其他列表相同的EAV(或6NF)方式实施此类列表.

"如果我采用抽象方法,它可以非常灵活,但是对于大量连接,查询会更复杂.但我不知道这是否会影响性能,执行这些'更复杂'的查询."

  1. 联接是关系数据库中的行人.问题不在于数据库,问题是SQL在处理连接时很麻烦,尤其是复合键.
  2. EAV和6NF数据库有更多的连接,就像行人一样,不多也不少.如果你必须手动编写每个SELECT代码,当然,麻烦很麻烦.
  3. 整个问题可以通过(a)通过EAV进行6NF和(b)实现目录来消除,您可以从中(c)生成所有基本SQL.消除了整个类的错误.
  4. 加入以某种方式付出代价是一种常见的神话.完全错误.连接是在编译时实现的,没有任何实质内容可以"花费"CPU周期.问题是要连接的表的大小,而不是这些表之间的连接成本.在正确的PK⇢FK关系上连接两个数百万行的表,每个表都有适当的索引(在父[FK]方面是唯一的;在子方面是唯一的)是瞬时的; ; 其中Child索引不是唯一的,但至少前导列是有效的,它更慢; 那里没有有用的索引,当然这很慢.这些都与加入成本无关.返回多行,瓶颈将是网络和磁盘布局; 不是联接处理.
  5. 因此,您可以随心所欲地获得"复杂",没有成本,SQL可以处理它.

我很想知道这两种方法的优缺点是什么.我可以想象一下自己,但我没有经验证实这一点.

  1. 对于那些没有取得进展的人来说,5NF(或3NF)是最简单和最好的,在实施,易用性(开发人员和用户),维护方面.缺点是,每次添加列时,都必须更改数据库结构(表DDL).在某些情况下这很好,但在大多数情况下,由于变更控制到位,相当繁重.其次,您必须更改现有代码(处理新列的代码不计算,因为这是必要的):实现良好标准,最小化; 在他们缺席的地方,范围是不可预测的.

  2. EAV(您已发布的内容)允许添加列而不进行DDL更改.这是人们选择它的唯一原因.(处理新列的代码不计算在内,因为这是必要的).如果实施得好,它不会影响现有代码; 如果没有,它会.但是你需要具备EAV功能的开发人员.当EAV实施得很糟糕时,它是恶劣的,比5NF做得差得多,但并不比Unnormalised更糟糕,这是大多数数据库所存在的(错误表示为"针对性能的非规范化").当然,保持强大的事务上下文更为重要(比在5NF/3NF中),因为列更加分散.同样,保留声明性参照完整性至关重要:我看到的混乱很大程度上是由于开发人员删除了DRI,因为它变成了"

  3. 假设服务器已针对预期目的进行了合理配置,则性能没有差异.(好吧,有一些特定的优化只能在6NF中实现,这在其他NF中是不可能的,但我认为这超出了这个线程的范围.)同样,EAV做得很糟糕会导致不必要的瓶颈,不会超过Unnormalised.

  4. 当然,如果你选择EAV,我建议更正式; 买全套钱; 和6NF一起去; 实施目录; 生成SQL的实用程序; 意见; 始终处理缺失数据; 完全消除空虚.这可以降低您对开发人员质量的脆弱性; 他们可以忘记EAV/6NF深奥的发布,使用视图,并专注于应用程序逻辑.

请原谅长篇文章.

  • 您是否考虑过修复维基百科页面?这将有助于许多人前往那里获取信息的第一个近似值,并因此得到强大的混淆. (23认同)
  • 谢谢你的客气话.没有这样的来源.有很好的教科书.网上提供的信息(对于任何事情,不仅仅是这个狭窄的主题)都是垃圾Wiki是一项平庸的研究.你得到你拍的东西.来自优秀的Uni的正式IT学位是最好的起点.众所周知,掌握来自与大师的合作.AFAIK只有一个其他公司提供这个主题的掌握程度:他们将其作为产品出售; 我把它作为一种服务出售,因为我相信它真的必须理解它,拥有它,而不是把它锁在产品中. (8认同)
  • 哇,谢谢你的回应,非常有趣.当然,我需要重新阅读几次,但我想问一下学习如何掌握6NF最可靠的资源是什么?维基百科和谷歌的结果没那么有用.你在哪里/怎么学习这个? (4认同)
  • @划分.我早年常常修复维基.但我很快厌倦了一遍又一遍地修复它.这是一个污水池,无论权利与否,任何人都可以编辑.它是由群众"贡献"的,出于政治目的,它在权威信息方面没有任何提供.为此,需要正规的高等教育.而这正在被摧毁. (3认同)
  • 凡/如何.好吧,我做了以上所有事情,我非常感谢我所拥有的优秀教师.我每年改进大约四个数据库,对于大型银行来说,这是我的热情/专业.如果我在这里说更多,那将是不合时宜的.如果您对更多细节感兴趣,请追逐我:profile⇢website⇢email.我可以自由回答你的问题.干杯. (2认同)

Wal*_*tty 9

在您的问题中,您同时提出了至少两个主要问题.这两个问题是EAV和gen-spec.

首先,我们来谈谈EAV.您的上一个表(object_id,field_id,value)本质上是一个EAV.EAV有一个好处,EAV也有下行空间.好处是结构非常通用,几乎可以容纳描述几乎所有主题的任何数据体.这意味着您可以继续进行设计和实施,无需进行数据分析,也无需了解主题,也不必担心错误的假设.缺点是在检索时,您必须在构建数据库之前进行数据分析,以便提出任何意义上的查询.这比检索效率要严重得多.但是你也会在检索效率方面遇到可怕的问题.只有两种方法可以了解这个陷阱:通过它生活或从那些人那里读到它.我推荐阅读.

其次,你有一个gen-spec案例.您的表(object_id,type_id)捕获gen-spec(泛化特化)模式以及相关表.如果我不得不在酒店和餐馆之间进行概括,我可以称之为"公共住宿"或"场地".但是我不确定我是否了解你的情况,而且你可能正在驾驶一些比这两个名字更普遍的东西.毕竟,你已经在你的列表中包含了"事件",并且事件不是我脑海中的一种场所.

我已经将其他人转介到关于gen-spec的读数以及之前回复中的关系模型.
当两个表格非常相似时,它们何时合并?

但是我犹豫是否会向同一个方向发送你,因为我不清楚你想在构建数据库之前想出数据的关系模型.一组数据的关系模型和相同数据的EAV模型几乎完全相互矛盾.在你甚至探索如何在数据的关系模型中表达gen-spec之前,你似乎必须做出这个选择.