Sql 与可空列或单独的表相比,使用键/值表有哪些优点?

Sql 与可空列或单独的表相比,使用键/值表有哪些优点?,sql,database-design,schema-design,Sql,Database Design,Schema Design,我正在升级前创建的付款管理系统。目前,它可以接受的每种付款类型都有一个表。它仅限于能够支付一件事情,而这次升级就是为了缓解这一问题。我一直在征求关于如何设计它的建议,我有以下基本想法: 每个付款类型有一个表,每个表上有几个公共列。(当前设计) 将所有付款与采用公共列的中心表(统一付款ID而不考虑类型)协调,并标识另一个表和行ID,该表和行ID具有专用于该付款类型的列 为所有付款类型创建一个表,并为不用于任何给定类型的列设置null 使用中心表的思想,但在键/值表中存储专门的列 我的目标是:不要慢

我正在升级前创建的付款管理系统。目前,它可以接受的每种付款类型都有一个表。它仅限于能够支付一件事情,而这次升级就是为了缓解这一问题。我一直在征求关于如何设计它的建议,我有以下基本想法:

  • 每个付款类型有一个表,每个表上有几个公共列。(当前设计)
  • 将所有付款与采用公共列的中心表(统一付款ID而不考虑类型)协调,并标识另一个表和行ID,该表和行ID具有专用于该付款类型的列
  • 为所有付款类型创建一个表,并为不用于任何给定类型的列设置null
  • 使用中心表的思想,但在键/值表中存储专门的列
  • 我的目标是:不要慢得离谱,尽可能地自我记录,在保持其他目标的同时最大限度地提高灵活性

    我不太喜欢1,因为每个表中都有重复的列。它反映了继承基类的付款类型类,该基类为所有付款类型提供功能。。。相反

    我最倾向于2,因为它与当前的设计一样具有“类型安全”和自我记录功能。但是,与1一样,要添加新的付款类型,我需要添加一个新表

    我不喜欢3,因为它“浪费了空间”,而且还不清楚哪些列用于哪些付款类型。文档可以在某种程度上减轻这种痛苦,但我公司的内部工具没有一种有效的方法来存储/查找技术文档

    我对4的论点是,在添加新的支付方法时,它可以减轻更改数据库的需要,但由于缺乏明确性,它比3更糟糕。目前,更改数据库不是一个问题,但如果我们决定开始让客户保留自己的数据库,这可能会成为一场物流噩梦

    所以,我当然有我的偏见。有谁有更好的主意吗?你认为哪种设计最合适?我应该根据什么标准来做决定?

    我的原则是不要无缘无故地重新设计。因此,我会选择选项1,因为这是您当前的设计,并且它有一个行之有效的工作记录

    把重新设计的时间花在新功能上。

    也许你应该看看

    比尔·卡温(Bill Karwin)接受的答案是针对键/值表(通常称为实体属性值(EAV))的特定参数

    。。虽然很多人似乎都喜欢 是的,我没有。这似乎是最重要的 灵活的解决方案,因此 最好的。然而,请记住这句格言 . 这里有一些 EAV的缺点:

    • 无法强制设置列(相当于
      非NULL
    • 无法使用SQL数据类型验证条目
    • 无法确保属性名称的拼写一致
    • 无法在任何给定属性的值上放置外键,例如。 用于查找表
    • 在传统的表格布局中获取结果既复杂又复杂 昂贵,因为要获得属性 从多行开始,您需要执行以下操作
      为每个属性加入
    EAV提供的灵活性程度 你需要在其他方面做出牺牲 区域,可能使您的代码 比实际情况复杂(或更糟) 我们一直在努力解决最初的问题 一种更传统的方式

    在大多数情况下,这是不必要的 有那么大的灵活性。 在OP关于产品的问题中 类型,创建 每种产品类型的表 特定于产品的属性,因此 有一些一致的结构 至少对 相同的产品类型

    只有当每一行都必须使用EAV时,我才会使用EAV 被允许有潜在的 一组不同的属性。当你 拥有一组有限的产品类型, EAV是过度杀伤力。类表 继承将是我的第一选择


    乍一看,我会选择选项2(或3):如果可能,概括。 我认为选项4关系不大,会使您的查询变得复杂。 当面对这些问题时,我通常用“用例”来面对这些选项:

    -设计2/3在执行此操作或此操作时表现如何?

    如果我是从头开始设计,我会选择第二个。它为您提供了所需的灵活性。然而,由于1号已经到位并正在运行,而且这是整个应用程序的核心,如果我不清楚您需要更改哪些查询、存储过程、视图、自定义项、报告、导入等,我可能会对进行重大设计更改持谨慎态度。如果这是我可以做的事情,风险相对较低(并且在适当的地方测试alrady),我可能会更改为解决方案2,否则您可能会产生新的更糟糕的错误

    在任何情况下,我都不会使用EAV表来进行类似的操作。它们在查询和性能方面都很糟糕,灵活性被高估了(询问用户是否愿意在不改变程序的情况下每年添加3-4次新类型,而以牺牲日常性能为代价)

    注意
    这个主题正在讨论中,而这个线程正在其他线程中引用,因此我已经对它进行了合理的处理,请接受我。我的意图是提供理解,以便您能够做出明智的决策,而不是仅仅基于标签的简单决策。如果你觉得很紧张,可以在空闲的时候分块读;饿的时候回来,不要在饿之前回来

    EAV到底有什么“不好”? 1简介 两者之间有区别