【问题标题】:Should I use flat tables or a normalized database?我应该使用平面表还是规范化数据库?
【发布时间】:2011-05-18 16:48:40
【问题描述】:

我目前正在开发一个 Web 应用程序,它使用 MySQL 数据库作为后端,在我继续之前,我需要知道什么更适合我的情况。

简单地说,在这个应用程序中,用户将能够使用任何数字字段(他们决定)构建自己的表单,现在我将它们全部存储在由外键链接的几个表中。我的一个朋友建议,为了保持“简单/快速”,我应该将每个用户的表单转换为一个平面表,以便从他们那里查询数据保持快速(以防大幅增长)。

我应该使用外键(索引等)汇集到关系表中的所有内容来规范数据库,还是应该为用户创建的每个新表单构建平面表?

显然,创建平面表的一些好处是数据分离(安全)和查询速度会降低。但是说真的,我会从中获得多少收益?我真的不想要 10000 个表并且一直在删除、更改和添加,但如果它比我会做的更好......我只需要一些输入。

谢谢

【问题讨论】:

标签: sql mysql normalization denormalization multiple-tables


【解决方案1】:

规范化 == 快速搜索、更易于维护索引、更慢的插入事务(在多行上)

非规范化 == 快速插入,通常在有大量插入时使用(收集和记录时序数据的数据仓库)

【讨论】:

    【解决方案2】:

    保持数据标准化。如果索引正确,很长一段时间内都不会遇到性能问题。

    关于安全性:扁平化方法需要您编写大量的创建/删除表、更改表等语句,即更多的代码和更多的故障点。

    拥有平面文件的唯一原因是您的用户可以直接连接到数据库(您仍然可以寻求行级安全性)。但在这种情况下,您实际上是在重新实现 phpmyadmin 的变体

    【讨论】:

    • +1 非常好的答案。 Martin 在很长一段时间后开始出现性能问题时该怎么办?我从来没有处理过这么多的数据/流量,所以不确定下一步是什么
    • a) 索引非常快 - 在 100 mio 中查找值。行表中一般只要对相关列进行索引就没有问题。所以在你遇到性能问题之前确实有很多空间。 b) 您可以按范围分区 表,例如为每1000 个用户ID 创建一个分区。您的查询将主要影响单个用户 ID,从而影响单个分区 - 所以这应该几乎线性扩展。
    【解决方案3】:

    我处理这个问题的方法是使用标准化的、可扩展的“属性”表,如下所示:

    Table: FormProperty
     id: pk
     form_id: fk(Form)
     key: varchar(128)
     value: varchar(2048)
    

    上面只是一个例子,但我在很多情况下都使用过这种模式,而且效果很好。唯一真正的“陷阱”是您需要将值序列化为字符串/varchar,然后将其反序列化为所需的任何内容,因此客户端需要承担一些额外的责任。

    【讨论】:

    • 要创建一个登录表单,例如,您可以: 插入 FormProperty(form_id, key, value) 值 (1, 'email', '' );插入 FormProperty(form_id, key, value) 值 (1, 'password', 'password');
    • 作为上述示例中 json/xml 的替代方案,您可以为字段属性创建一个附加表并通过外键链接它/它们。
    【解决方案4】:

    ...在此应用程序中,用户将能够使用任何数字字段构建自己的表单...

    哎呀!那么,当用户在本质上为您做出数据库决策时,您如何可能进行任何形式的规范化。

    我认为您要么需要逐步管理它,要么让您的怪胎旗帜飘扬,并继续购买硬件以跟上用户真正开始使用它时您将要获得的震撼......举个例子,看看当用户开始了解如何在 SharePoint 中创建新的表单和视图时会发生什么......CRIKY!谈论范围蔓延!

    【讨论】:

    • 明确定义他们可以创建哪些字段/输入。限制他们可以进行的自定义数量。范围是为项目定义的,除非我这样做,否则不应更改。感谢您的意见。
    • @Steve B。您可能会考虑他们可以添加的通用字段的调色板,这些字段是标准化的。例如:员工 id 进入 emp_table,这样人们就不会重新创建轮子。
    • 我有一个包含 15 个左右输入的列表,用户可能会在表单上使用这些输入,这可能会增长,但几乎可以满足他们需要的任何操作,它们存储在静态表中并通过 id 链接到用户表单。
    【解决方案5】:

    保持数据标准化。如果您有正确的索引,系统应该会保持快速。

    如果你真的想走得更快,那么将架构切换到 bigDB /couchDB 等键值数据库之一。这是完全非规范化的并且非常非常快。

    【讨论】:

      【解决方案6】:

      在运行时更改架构很少是一个好主意。您要考虑的是 EAV(实体-属性-值)模型。

      维基百科有some very good info 的优缺点,以及实现细节。应尽可能避免 EAV,但对于像您这样的情况,每个表单的列数未知,EAV 值得考虑。

      【讨论】:

      • 我从未听说过 EAV,但它似乎与我在上面使用带有键/值对的表提出的解决方案相似。我上面提出的解决方案是否类似于您建议的 EAV 解决方案?我只是好奇,因为我想了解更多有关 EAV 建模的信息。
      • @Matt:是的,完全正确。在您的情况下,E=form_id,A=key,V=value。在修改版本中,您可以为不同的数据类型添加额外的值列,因此您可以通过索引和聚合等提高效率,但这也增加了查询的复杂性。
      【解决方案7】:

      经验法则。从规范化到非规范化比反过来更容易。

      从合理级别的数据库规范化开始(合理的意思是可读、可维护和高效,但不会过早优化),然后如果您在成长过程中遇到性能问题,您可以选择研究非规范化的方法提高性能。

      【讨论】:

      猜你喜欢
      • 2018-07-08
      • 2013-07-26
      • 2017-01-27
      • 2020-05-08
      • 2010-12-11
      • 1970-01-01
      • 2011-01-25
      • 2011-02-06
      • 2012-03-22
      相关资源
      最近更新 更多