关于sql:[在可为空的列或单独的表上使用键/值表的缺点是什么?

What are the [dis]advantages of using a key/value table over nullable columns or separate tables?

我正在升级我之前创建的付款管理系统。目前,它可以接受的每种付款方式都有一张表格。它仅限于只能支付一件东西,此升级可以缓解此问题。我一直在寻求有关如何设计它的建议,并且我有以下基本想法可用于:

  • 每种付款类型都有一张表格,每张表格上都有一些共同的列。 (当前设计)
  • 使用中心表协调所有付款,该中心表具有公共列(统一付款ID,而不管类型如何),并标识另一个表和行ID,其中该表和行ID具有专门用于该付款类型的列。
  • 对于所有付款类型都有一张表格,将没有用于任何给定类型的列设为空。
  • 使用中心表的想法,但将专用列存储在键/值表中。
  • 我的目标是:不要荒谬地缓慢,尽可能自我记录,并在保持其他目标的同时最大程度地提高灵活性。

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

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

    我不喜欢3,因为它的"浪费空间",而且尚不清楚立即将哪种列用于哪种付款类型。文档可以减轻这种麻烦,但是我公司的内部工具没有一种有效的方法来存储/查找技术文档。

    我为4给出的论据是,这将减轻添加新的付款方式时需要更改数据库的麻烦,但是由于缺乏明确性,它比3遭受的影响更糟。当前,更改数据库不是问题,但是如果我们决定开始让客户继续使用自己的数据库,这可能会成为后勤上的噩梦。

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


    注意
    正在讨论此主题,并且在其他线程中引用了该线程,因此,我已对其进行了合理的处理,请多多包涵。我的目的是提供理解,以便您可以做出明智的决定,而不是仅仅基于标签的简单决定。如果您觉得它很强烈,可以在闲暇时分批阅读;饿的时候回来,而不是回来。

    确切地说,关于EAV,"坏"是什么?

    1引言

    EAV正确执行与错误执行之间存在差异,就像3NF正确执行与错误执行之间存在差异。在我们的技术工作中,我们需要精确地确定哪些有效,哪些无效。关于什么表现良好,什么没有。一揽子声明是危险的,会误导人们,从而阻碍有关问题的进展和普遍理解。

    我不赞成或反对任何东西,除非非熟练工人实施得不好,并且错误地陈述了对标准的遵守程度。在这里我会感到误解的地方,我将尝试解决它。??

    归一化也常常被误解,因此可以一言以蔽之。 Wiki和其他免费资源实际上发布了完全荒谬的"定义",这些定义没有学术依据,存在供应商偏见,从而可以验证其不符合标准的产品。有一个科德出版了他的十二条规则。我实施的最低5NF足以满足大多数要求,因此我将其用作基准。简而言之,假设读者可以理解"第三范式"(至少不要混淆定义)...

    2第五范式

    2.1定义

    第五范式定义为:

    • 每列与主键之间只有1 :: 1的关系
    • 在表格或任何其他表格中没有其他列
    • 结果是在任何地方都没有重复的列;没有更新异常(不需要触发器或复杂的代码来确保在更新列时,其重复项可以正确更新)。
    • 它提高了性能,因为(a)它影响较少的行,并且(b)由于减少了锁定而提高了并发性

    我的区别在于,不是数据库是否已针对特定的NF进行了规范化;数据库只是简单地归一化。就是每个表都被规范化为特定的NF:有些表可能只需要1NF,另一些表需要3NF,而另一些表则需要5NF。

    2.2性能

    曾经有一段时间,人们以为标准化不提供性能,因此他们不得不"为实现性能而进行非规范化"。感谢上帝,这个神话被揭穿了,如今,大多数IT专业人员都意识到规范化数据库的性能更好。数据库供应商为标准化数据库而不是去杂化文件系统进行优化。事实是,"未规范化"是,数据库没有首先进行规范化(并且性能很差),还没有进行规范化,因此他们进行了进一步的加扰以提高性能。为了进行非规范化,必须先对其进行忠实的规范化,这从未发生过。我已经重写了几十个这样的"性能降低规格化"数据库,提供了忠实的规范化,仅此而已,它们的运行速度至少快了十倍,多达一百倍。此外,它们仅需要磁盘空间的一小部分。太行人了,我以书面形式保证锻炼。

    2.3限制

    5NF的局限性或全部范围是:

    • 它不处理可选值,并且必须使用Null(许多设计人员不允许Null,而使用替代项,但是如果未正确且一致地实现,则存在局限性)
    • 您仍然需要更改DDL来添加或更改列(并且越来越多的要求添加在限制后添加最初未被标识的列;更改控制很繁琐)
    • 尽管由于归一化(读取:消除重复项和混乱的关系),复杂的查询(例如,透视(生成行的报告或行的汇总,以列表示))和"列访问",提供了最高的性能,数据仓库操作很困难,仅那些操作就不能很好地执行。并不是说这仅是由于可用的SQL技能水平,而不是由于引擎。

    3第六范式

    3.1定义

    第六范式定义为:

    • 关系(行)是主键加上最多一个属性(列)

    它被称为不可归约范式,终极NF,因为无法执行进一步的归一化。尽管它在90年代中期在学术界进行了讨论,但直到2003年才正式宣布。对于那些喜欢通过混淆关系,relvars,"关系"等来贬低关系模型的形式的人,所有的废话都可以之所以被搁置,是因为上面的定义正式地标识了不可约关系,有时也称为原子关系。

    3.2进度

    6NF提供的增量(5NF不提供)是:

    • 正式支持可选值,因此消除了空问题

      • 副作用是,可以在不更改DDL的情况下添加列(稍后再介绍)
    • 轻松旋转
    • 简单直接的列访问

      • 它使该部门的绩效水平更高(而不是原始形式)

    让我说,我(和其他人)在20年前就提供了增强的5NF表,明确地用于数据透视,没有任何问题,因此允许(a)使用简单的SQL,并且(b)提供非常高的性能;很高兴知道该行业的学术巨头已经正式定义了我们正在做的事情。一夜之间,我的5NF桌子被重命名为6NF,而我却没有举手。第二,我们只在需要的地方这样做。再次,是将表而不是数据库标准化为6NF。

    3.3 SQL限制

    这是一种繁琐的语言,尤其是re joins,并且做任何适度复杂的事情都会使其变得非常繁琐。 (这是大多数编码人员不理解或使用子查询的独立问题。)它支持5NF所需的结构,但仅支持这种结构。为了实现稳定可靠的实施,必须实施其他标准,其中可能包括其他目录表的一部分。到90年代初,SQL的"使用依据"日期已经过去了。它完全没有对6NF表的任何支持,非常需要替换。但这就是我们所拥有的,因此我们只需要处理它即可。

    对于那些一直在执行标准和附加目录表的人来说,扩展目录以提供支持6NF结构到标准所需的能力并不是一件认真的工作:哪些列属于哪些表,以什么顺序;强制/可选;显示格式;等。本质上是完整的MetaData目录,与SQL目录结合在一起。

    请注意,每个NF都包含其中的每个先前NF,因此6NF包含5NF。我们并没有为了提供6NF而破坏5NF,而是提供了从5NF的进展;在缺少SQL的地方,我们提供了目录。这意味着基本限制,例如外键;通过SQL声明式引用完整性提供的值域;以及数据类型;检查;而在5NF级别的规则保持不变,并且这些约束没有被颠覆。无论如何,引入6NF并不会降低符合标准的5NF数据库的高质量和高性能。

    3.4目录

    保护用户(任何报告工具)和开发人员免遭从5NF到6NF的跃迁非常重要(成为应用程序编码极客是他们的工作,成为数据库极客是我的工作。 )。即使在5NF的情况下,这始终是我的设计目标:拥有适当的Normalized数据库和最少的Data Directory,实际上非常易于使用,并且我没有办法放弃它。请记住,由于正常的维护和扩展,6NF结构会随时间而变化,因此会定期发布数据库的新版本。毫无疑问,从6NF表构造5NF行所需的SQL(在5NF下已经很麻烦)更加麻烦。感激的是,这完全没有必要。

    由于我们已经有了目录,该目录标识了完整的6NF-DDL-SQL-does-not-provide,因此,如果您愿意,我编写了一个小实用程序来读取目录并:

    • 生成6NF表DDL。
    • 生成6NF表的5NF视图。这使用户能够幸福地不了解它们,并赋予他们与5NF相同的功能和性能。
    • 生成针对6NF结构进行操作所需的完整SQL(不是模板,我们单独拥有它们),然后由编码人员使用。它们会从乏味和重复中释放出来,而这在其他情况下是必需的,并且可以自由地专注于应用程序逻辑。

    我没有编写用于Pivoting的实用程序,因为消除了5NF中存在的复杂性,并且现在它们像编写5NF-enhanced-for-pivoting一样非常容易编写。此外,大多数报告工具都提供透视功能,因此我只需要提供包含大量统计信息的功能,这些功能需要在服务器上执行后才能交付给客户。

    3.5性能

    每个人都有自己的"疾病"受苦,他们的十字架要忍受;我碰巧迷上了性能。我的5NF数据库的性能很好,所以让我向您保证,在投入生产之前,我运行的基准测试超出了必要的标准。 6NF数据库的性能与5NF数据库完全相同,没有改善,也没有恶化。这并不奇怪,因为"复杂的" 6NF SQL所做的(而5NF SQL却没有)唯一的作用就是执行更多的联接和子查询。

    您必须研究神话。

    • 对问题进行基准测试(即检查查询的执行计划)的任何人都将知道,Joins Cost Nothing,它是一个编译时解决方案,它们对执行时没有影响。
    • 是的,当然,要连接的表数是多少?被连接的表的大小;是否可以使用索引;被连接的密钥的分布;等等,都花些钱
    • 但是联接本身不花任何费用。
    • 如果对非标准化数据库中的五个(较大)表进行查询,则比对相同数据库中十个(较小)表进行等效查询的查询要慢得多。关键是,四个或九个Join都不花任何钱;他们没有考虑到性能问题;每个Join上的选定集合都将包含在其中。

    3.6收益

  • 无限制的列访问。这就是6??NF真正脱颖而出的地方。直接的柱状访问是如此之快,以至于不需要从专门的DW结构中获得速度就可以将数据导出到数据仓库。

    我对一些DW的研究(尚未完成)表明,它们一致地按列存储数据,而不是按行存储数据,这正是6NF所做的。我很保守,所以我不会宣布6NF会取代DW,但就我而言,它消除了对DNF的需求。

  • 比较6NF中可用的功能与5NF中不可用的功能(例如,Pivoting)是不公平的,它们显然运行得快得多。

  • 这是我们第一个真正的6NF数据库(具有完整的目录等;与之相比,始终只有5NF仅在必要时进行了增强;后来变成6NF),并且客户非常满意。当然,交付后我一直在监视性能,并且为下一个6NF项目确定了一种甚至更快的列访问方法。当我这样做时,可能会为DW市场带来一些竞争。客户还没有准备好,我们也不会修复未损坏的产品。

    3.7大约6NF到底是什么?

    请注意,并不是每个人都会以尽可能多的形式,结构和对标准的遵守来从事这项工作。因此,从我们的项目中得出结论,即所有6NF数据库都运行良好且易于维护,这是很愚蠢的。得出所有6NF数据库性能不佳,难以维护的结论(通过查看其他实现,这同样愚蠢)。灾难。与往常一样,在进行任何技术努力后,除相关技能集外,最终的性能和维护的简便性还严格取决于形式,结构和对标准的遵守。

    3.8可用性

    请不要暴露自己,并索要超出标准商业惯例范围的任何东西,例如"已发布的参考资料",客户是澳大利亚的银行,整个实施过程是保密的;但我有空去拜访潜在客户。也欢迎您在我们位于悉尼的办公室中查看(但不能复制)文档。该方法论(除公开提供的6NF教育之外的结构和标准)和实用程序是我们的专有知识产权,可用于分配任务。在此阶段,我仅作为任务的一部分出售它,因为(a)我需要合理地确保该项目的成功(以免损害我们的声誉),并且(b)仅仅依靠我们的成功项目是不够的将其归类为"已准备好投放市场"的成熟度。

    我很高兴继续回答问题,并提供有关6NF目录的有用信息,提供有关什么有效,什么无效的建议,等等,而无需实际发布我们的IP(文档)。我也很高兴为您运行合格的基准测试。

    4实体属性值

    披露:经验。我已经检查了其中一些,主要是医院和医疗系统。我已经对其中两个执行了纠正任务。海外供应商提供的初始交付虽然不算足够,但还算足够,但本地供应商实施的扩展却一团糟。但是,几乎没有人们在此站点上发布过有关re EAV的灾难。几个月的紧张工作将它们很好地固定了。

    4.1它是什么

    对我来说显而易见的是,我从事的EAV实现只是第六范式的子集。实施EAV的人之所以这样做,是因为他们想要6NF的某些功能(例如,无需DDL更改即可添加列的能力),但是他们不具备实现真正的6NF的学术知识,也不具备实施和管理6NF的标准和结构。安全地。甚至原始的提供者都不知道6NF,或者说EAV是6NF的子集,但是当我向他们指出时,他们很同意。由于在EAV社区中尚未正式确定有效且有效地提供EAV以及实际上6NF所需的结构(目录;视图;自动代码生成),并且在大多数实现中都缺少,因此我将EAV归类为混蛋第六范式。

    4.2准确地说,EAV是"坏"的吗?

    按照此主题和其他主题中的评论,是的,EAV做得不好是一场灾难。更重要的是(a)它们太糟糕了,以至于5NF(忘记6NF)所提供的性能都丧失了;(b)尚未实现与复杂性的普通隔离("强迫"编码器和用户使用繁琐的导航)。如果他们没有实施目录,那么各种可预防的错误也将无法避免。对于不好的(EAV或其他)实现,所有这些都可能是正确的,但与6NF或EAV无关。我工作的两个项目都具有足够的性能(可以改进,但不会因EAV而导致性能下降),并且很好地隔离了复杂性。当然,它们远不及我的5NF数据库或真正的6NF数据库的质量或性能,但考虑到对EAV社区中已发布问题的了解程度,它们还是很公平的。这些不是在这些页面中被称为EAV的灾难和不合标准的废话。

    5空值

    有一个众所周知且已记录在案的问题,称为"空问题"。它本身就值得写一篇论文。对于此帖子,只需说:

    • 问题实际上是可选值或缺失值;这里考虑的是表设计,因此没有Nulls与Nullable列
    • 实际上,这并不重要,因为无论您是否使用Nulls / No Nulls / 6NF排除缺失值,您都必须为此编写代码,这正是问题所在,正在处理无法避免的缺失值

      • 当然是纯6NF除外,它消除了Null问题
      • 处理缺失值的编码仍然存在

        • 除了,随着自动生成SQL代码,呵呵
    • 空值对于性能而言是个坏消息,而且数十年前,我们中的许多人决定不让空值进入数据库(传递的参数和结果集中的空值表示缺失值是可以的)

      • 这意味着一组Null替换项和boolean列以指示缺少的值
    • 空值导致固定的len列可变为len;可变的len列永远不要在索引中使用,因为在遍历或潜水期间,必须对每个索引条目的每次访问进行一些"解包"。

    6位置

    我不是EAV或6NF的支持者,我是质量和标准的支持者。我的位置是:

  • 始终以各种方式按照自己所知道的最高标准来做任何事情。

  • 对于关系数据库(对我来说5NF),归一化为第三范式的要求最小。数据类型,声明性引用完整性,事务,规范化都是数据库的基本要求;如果缺少它们,则它不是数据库。

    • 如果必须"对性能进行非规范化",则说明您犯了严重的"规范化"错误,您的设计未进行规范化。时期。相反,不要"去规范化",而是学习"规范化"和"规范化"。
  • 没有必要做额外的工作。如果5NF可以满足您的要求,请不要实施更多。如果您需要可选值或添加列而无需DDL更改或完全消除Null问题的能力,则仅在需要它们的那些表中实施6NF。

  • 如果这样做,则仅由于SQL无法为6NF提供适当的支持,您将需要实现:

    • 简单有效的目录(列混搭和数据完整性损失根本无法接受)
    • 通过视图对6NF表进行5NF访问,以将用户(和开发人员)与繁琐(而不是"复杂")的SQL隔离开
    • 编写或购买实用程序,以便您可以生成繁琐的SQL以从6NF表构造5NF行,并避免编写相同的语句
    • 测量,监视,诊断和改进。如果您有性能问题,则可能是(a)规范化错误或(b)编码错误。时期。备份一些步骤并修复它。
  • 如果您决定使用EAV,请按照6NF识别它,并正确实施。如果这样做,那么您将有一个成功的项目。如果不这样做,您将保证有狗的早餐。

  • 6.1没有免费的午餐

    该格言已被提及,但实际上已被滥用。它的实际应用方式如上所述:如果您想获得6NF / EAV的好处,那么您最好也愿意为获得6NF / EAV做必要的工作(目录,标准)。当然,必然的结果是,如果您不做这项工作,那么您将无法获得好处。数据类型没有"丢失";价值域;外键;检查;规则。关于性能,对于6NF / EAV并没有性能损失,但是对于不合格的不合标准的工作始终会存在相当大的性能损失。

    7个具体问题

    最后。考虑到上述情况,并且这是一个由小型团队组成的小型项目,因此毫无疑问:

    • 请勿使用EAV(或6NF)
    • 不要使用Nulls或Nullable列(除非您希望破坏性能)
    • 请勿在通用付款列中使用一个付款表
    • 以及每个PaymentType的子表,每个子表都有其特定的列
    • 所有完全强制转换并受其约束。

    • "另一个row_id"业务是什么?为何有些人在未移动的东西上贴上ID,而不检查它是鹿还是鹰?不可以。孩子是被抚养的孩子。关系是1 :: 1。孩子的PK是父母的PK,即常见的付款表。这是一个普通的Supertype-Subtype集群,区分项是PaymentTypeCode。子类型和超类型是关系模型的普通部分,在数据库以及任何良好的建模工具中都得到了充分满足。

      当然,对关系数据库一无所知的人认为他们在30年后发明了它,并给它起了个有趣的新名字。或更糟糕的是,他们故意重新标记它并声称自己拥有它。直到一些贫穷的草皮,经过一点教育和专业自豪,才暴露出无知或欺诈。我不知道它是哪一个,但它是其中之一。我只是在陈述事实,这些事实很容易确认。

    感谢与我在一起直到最后。

    A.对评论的回应

    A.1归因

    我说"我对RM忠实",并提到"行业巨人",我认为IT专业人员会理解这意味着什么。谦虚的歉意。

  • 我没有个人或私人或特殊定义。关于以下定义(例如命令)的所有陈述:

    • 正常化,
    • 普通表格,以及
    • 关系模型。

      请参阅EF Codd和CJ Date撰写的许多原始文本(在网络上免费提供)

      最新的是时间数据和关系模型,作者:CJ Date,休·达尔文,尼科斯·洛伦佐斯(Nikos A Lorentzos)

      除了那些文字

      "我站在巨人的肩膀上"
  • 本质,主体,有关上述实现的所有陈述(例如,主观和第一人称)都是基于经验的;在美国和澳大利亚的大型金融机构中,以商业组织(聘请顾问或经营咨询公司)的身份实施上述原则和概念超过32年。

    • 这包括纠正或替换不合标准或非关系实现的大量大型任务。
  • 关于第六范式的零问题
    可以在以下位置找到与标题相关的免费白皮书(它并不单独定义"空问题"):
    http://www.dcs.warwick.ac.uk/~hugh/TTM/Missing-info-without-nulls.pdf。

    在第6页上可以找到6NF的"简明扼要"定义(对其他NF经验丰富的人有意义)。
  • A.2证明文件

  • 如一开始所说,此职位的目的是为了应对社区中普遍存在的错误信息,为社区提供服务。
  • 如果确定了特定的陈述,则可以提供证据证明陈述,这些陈述是为贯彻上述原则而做出的;并且在同样程度上也证明了其他人发布的错误陈述(对此帖子是对此的回应)。如果要打a头,请确保比赛场地平整
  • 以下是我可以立即使用的一些文档,以开始使用(我在NZ上任职,将在几天之内提供更多文档,客户名称必须混淆)。

    a。大银行
    这是最好的例子,因为它是出于本文中明确的原因进行的,并且已经实现了目标。他们有Sybase IQ(DW产品)的预算,但是当我们完成项目时,报告是如此之快,所以他们不需要它。贸易分析统计数据是我的5NF加上可扩展的扩展,事实证明是6NF,如上所述。我认为注释中提出的所有问题均已在文档中得到回答,但以下情况除外:
    -行数:
    -旧数据库未知,但可以从其他统计数据中推断得出
    -新数据库=超过100M的20个表,超过10B的4个表。

    b。小型金融学院A部分
    B部分-肉
    C部分-参考图
    D部分-附录,之前/之后的指数审核(每个索引1行)
    注意四个文档;第四项仅适用于希望检查详细索引更改的人员。他们正在运行一个第三方应用程序,该应用程序无法更改,因为本地供应商已经停业,外加120%的扩展名,他们可以但不希望更改。我们之所以被召集是因为他们将Sybase升级到了一个新版本,该版本更快,它改变了各种性能阈值,从而没有造成死锁。在这里,我们对除db模型之外的服务器中的所有内容进行了归一化,以(事先保证)消除死锁的目标(对不起,我在这里不做解释:那些争论"非规范化"问题的人会变成粉红色)适合这个)。它包括"将表拆分到存档数据库中以提高性能"的逆转,这是另一篇文章的主题(是的,新的单个表的执行速度比两个溢出的表要快)。此练习也适用于MS SQL Server [插入重写版本]。

    c。耶鲁纽黑文医院
    那是耶鲁大学医学院,他们的教学医院。多年来一直在支持他们。 Sybase之上的第三方应用程序。统计数据的问题是,他们有80%的时间仅在指定的测试时间收集快照,但是没有一致的历史记录,因此没有"映像前"可以与我们的新一致统计数据进行比较。我不知道有其他公司可以以自动化方式在同一张图表上获得Unix和Sybase内部统计信息。现在,网络就是门槛(请相信读者,这是一件好事)。

  • 一开始就是已经被发布的东西清除了。以后再说。好的,让我们有一些证据来支持"非规范化可以提高性能"的概念,等等。轮到您了。

    A.3长度

  • 我不会为您的长篇大论或简明扼要而道歉。注意力不集中的人(没有违法行为,如今已经成为现实),或者不熟悉关系技术或术语的人应该参考源文本或该技术的支持者。
  • 根据定义,不包括Wiki,以及任何贬低Wiki技术的人,例如该帖子所针对的海报。大象不可能定义瞪羚。如果它们确实假设了瞪羚的生活,我们就不应该听它们。

  • 也许您应该看这个问题

    Bill Karwin接受的答案进入了针对键/值表的特定参数,通常称为实体属性值(EAV)

    .. Although many people seem to favor
    EAV, I don't. It seems like the most
    flexible solution, and therefore the
    best. However, keep in mind the adage
    TANSTAAFL. Here are some of the
    disadvantages of EAV:

    • No way to make a column mandatory (equivalent of NOT NULL).
    • No way to use SQL data types to validate entries.
    • No way to ensure that attribute names are spelled consistently.
    • No way to put a foreign key on the values of any given attribute, e.g.
      for a lookup table.
    • Fetching results in a conventional tabular layout is complex and
      expensive, because to get attributes
      from multiple rows you need to do
      JOIN for each attribute.

    The degree of flexibility EAV gives
    you requires sacrifices in other
    areas, probably making your code as
    complex (or worse) than it would have
    been to solve the original problem in
    a more conventional way.

    And in most cases, it's an unnecessary
    to have that degree of flexibility.
    In the OP's question about product
    types, it's much simpler to create a
    table per product type for
    product-specific attributes, so you
    have some consistent structure
    enforced at least for entries of the
    same product type.

    I'd use EAV only if every row must
    be permitted to potentially have a
    distinct set of attributes. When you
    have a finite set of product types,
    EAV is overkill. Class Table
    Inheritance would be my first choice.


    如果我从头开始设计,我会选择第二个。它为您提供所需的灵活性。但是,由于第1号已经就绪并且可以正常工作,并且在整个应用程序中显得很重要,因此我可能会警惕在不进行确切查询,存储过程,视图,UDF,报告,导入内容确切了解的情况下进行重大设计更改等等,你将不得不改变。如果可以用较低的风险(并且有良好的测试方法)来解决此问题,那么我可能会寻求解决方案2的更改,否则您可能会引入新的更严重的错误。

    在任何情况下,我都不会将EAV表用于此类内容。它们对于查询和性能而言是可怕的,并且灵活性被高估了(如果用户希望每年更新3-4次新类型而无需更改程序就以日常性能为代价,请咨询用户)。


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

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


    乍一看,我会选择选项2(或3):尽可能概括一下。
    我认为选项4不是非常相关,它将使您的查询变得复杂。
    当遇到这些问题时,我通常会以"用例"来面对这些选择:
    -执行此操作或此操作时,设计2/3的行为如何?