在可空列或单独表中使用键/值表的缺点是什么?

时间:2010-10-29 21:38:25

标签: sql database-design schema-design

我正在升级我刚才创建的支付管理系统。它目前有一个表可以接受每种付款方式。它仅限于能够支付一件事,这个升级是为了缓解。我一直在询问我应该如何设计它的建议,我有这些基本的想法:

  1. 每种付款类型都有一个表格,每个付款类型都有几个常用列。 (当前设计)
  2. 使用带有公共列的中央表协调所有付款(统一付款ID,无论类型如何),并标识具有专门针对该付款类型的列的另一个表和行ID。
  3. 为所有付款类型设置一个表,并将未用于任何给定类型的列设为空。
  4. 使用中心表的想法,但将专门的列存储在键/值表中。
  5. 我的目标是:不要过于缓慢,尽可能自我记录,并在保持其他目标的同时最大限度地提高灵活性。

    由于每个表中的重复列,我不太喜欢1。它反映了继承基类的支付类型类,该基类为所有支付类型提供功能...... ORM反向?

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

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

    我给出的4个论点是,它可以减少在添加新的付款方式时需要更改数据库的情况,但是由于缺乏明确性,它会比3更糟。目前,更改数据库不是问题,但如果我们决定开始让客户保留自己的数据库,它可能会成为一个后勤噩梦。

    所以,我当然有偏见。有没有人有更好的想法?您认为哪种设计最合适?我应该根据什么标准做出决定?

5 个答案:

答案 0 :(得分:29)

答案 1 :(得分:9)

也许你应该看this question

Bill Karwin接受的答案涉及通常称为实体属性值(EVA)的键/值表的特定参数

  

..虽然很多人似乎都很青睐   EAV,我没有。这似乎是最多的   灵活的解决方案,因此   最好。但是,请记住这句格言   TANSTAAFL。这是一些   EAV的缺点:

     
      
  • 无法强制列(相当于NOT NULL)。
  •   
  • 无法使用SQL数据类型来验证条目。
  •   
  • 无法确保属性名称拼写一致。
  •   
  • 无法将外键放在任何给定属性的值上,例如   查找表。
  •   
  • 在传统的表格布局中获取结果非常复杂   昂贵,因为要获得属性   从你需要做的多行   每个属性JOIN
  •   
     

EAV给出的灵活程度   你需要在其他方面做出牺牲   区域,可能使您的代码成为   比它复杂(或更糟)   一直在解决原来的问题   一种更传统的方式。

     

在大多数情况下,这是不必要的   具有这种程度的灵活性。   在OP关于产品的问题上   类型,创建一个更简单   每种产品类型的表格   产品特定的属性,所以你   有一些一致的结构   至少强制执行的条目   相同的产品类型。

     

我只有在每一行必须时才使用EAV   被允许可能有一个   不同的属性集。当你   有一组有限的产品类型,   EAV太过分了。班级表   继承将是我的第一选择。

答案 2 :(得分:2)

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

改为在新功能上花费重新设计时间。

答案 3 :(得分:2)

如果我从头开始设计,我会选择第二名。它为您提供所需的灵活性。然而,第1号已经到位并正在工作,而这对于整个应用程序来说相当重要,我可能会警惕做出重大的设计更改而不知道究竟是什么查询,存储过程,视图,UDF,报告,导入等你必须改变。如果这是我可以用相对较低的风险做的事情(以及适当的测试结果)。我可能会改变解决方案2,否则你可能会引入新的更糟糕的错误。

在任何情况下我都不会使用EAV表来做这样的事情。它们对于查询和性能而言非常糟糕,并且灵活性被高估了(询问用户是否希望能够每年添加3-4次新类型,而不会以日常性能为代价更改程序)。

答案 4 :(得分:0)

乍一看,我会选择2(或3):如果可能,请概括。 我认为选项4不是很关系,会让你的查询变得复杂。 当遇到这些问题时,我通常会用“用例”来面对这些选项:
- 当这个或这个操作时,设计2/3会如何表现?