我应该使用平面表还是规范化数据库?
Posted
技术标签:
【中文标题】我应该使用平面表还是规范化数据库?【英文标题】:Should I use flat tables or a normalized database? 【发布时间】:2011-05-18 16:48:40 【问题描述】:我目前正在开发一个 Web 应用程序,它使用 mysql 数据库作为后端,在我继续之前,我需要知道什么更适合我的情况。
简单地说,在这个应用程序中,用户将能够使用任何数字字段(他们决定)构建自己的表单,现在我将它们全部存储在由外键链接的几个表中。我的一个朋友建议,为了保持“简单/快速”,我应该将每个用户的表单转换为一个平面表,以便从他们那里查询数据保持快速(以防大幅增长)。
我应该使用外键(索引等)汇集到关系表中的所有内容来规范数据库,还是应该为用户创建的每个新表单构建平面表?
显然,创建平面表的一些好处是数据分离(安全)和查询速度会降低。但是说真的,我会从中获得多少收益?我真的不想要 10000 个表并且一直在删除、更改和添加,但如果它比我会做的更好......我只需要一些输入。
谢谢
【问题讨论】:
正常化,直到它受伤。 :) 不是一个真正的答案...但您始终可以使用***作为指导。这是***的数据库架构:commons.wikimedia.org/wiki/File:Mediawiki-database-schema.png @shamazing 然后去规范化直到它工作。 80)) 我最近也问了一个类似的问题,可能是换个角度programmers.stackexchange.com/questions/212822/… 【参考方案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', '...在此应用程序中,用户将能够使用任何数字字段构建自己的表单...
哎呀!那么,当用户在本质上为您做出数据库决策时,您如何可能进行任何形式的规范化。
我认为您要么需要逐步管理它,要么让您的怪胎旗帜飘扬,并继续购买硬件以跟上用户真正开始使用它时您将要获得的震撼......举个例子,看看当用户开始了解如何在 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】:经验法则。从规范化到非规范化比反过来更容易。
从合理级别的数据库规范化开始(合理的意思是可读、可维护和高效,但不会过早优化),然后如果您在成长过程中遇到性能问题,您可以选择研究非规范化的方法提高性能。
【讨论】:
巧合的是,我正在阅读这个***.com/questions/4301089/… 谢谢,鲍勃。你提出了一个很好的观点。非常感谢。以上是关于我应该使用平面表还是规范化数据库?的主要内容,如果未能解决你的问题,请参考以下文章