需要描述的时间很长,所以我将简化示例。
我想创建一个表单创建系统(用户可以创建表单,添加字段等...)。让我们关注复选框vs textarea。
复选框的值可以是0或1,具体取决于选中的状态。 textarea必须是LONGTEXT类型。
所以在数据库中,这给了我3个关于表field_value结构的选择:
1
checkbox_value (TINYINT) | textarea_value (MEDIUMTEXT)
这意味着没有输入将使用表的所有列。桌子会浪费一些空间。
2
allfield_value (MEDIUMTEXT)
这意味着对于复选框,我会在MEDIUMTEXT中存储一个非常小的值,这是没用的。
3
tblcheckbox.value
tbltextarea.value
现在每个字段有一个单独的表。这在空间方面是最优的,但是在应用程序的整个上下文中,我可能期望必须读取超过100个表 - 具有多个JOIN的1个查询)以生成显示表单的单个页面。
在您看来,最好的方法是什么?
答案 0 :(得分:3)
不要考虑EAV数据模型。将数据放入其中很容易,但很难获取数据。它不会扩展。它没有数据完整性。如果正确建模数据,您必须自己编写大量代码来执行RDBMS为您所做的事情。尝试使用RDBMS创建可满足任何未来需求的通用表单管理系统是Inner-Platform Effect反模式的一个示例。
(顺便说一下,如果你确实使用了EAV,请不要尝试将所有属性连接成一行。你已经评论过MySQL对每个查询的连接数有限制,但即使你可以生活在其中,它表现不佳。只需每行获取一个属性,并在应用程序代码中对其进行排序。循环从数据库中获取的属性行,并按字段填充对象。这意味着更多的代码你要写,但这是内部平台效应的代价。)
如果要以关系方式存储表单数据,则每个属性都将位于其自己的列中。这意味着您需要为表单设置自定义表(如果表单支持多值字段,则需要设置实际的表集)。根据每个给定表单字段的含义命名列,而不是像“checkbox_value”那样通用的名称。根据给定表单字段的需要选择数据类型,而不是一个通用的MEDIUMTEXT或VARCHAR(255)。
如果要以非关系方式存储表单数据,则可以获得更大的灵活性。您可以使用非关系型文档存储,例如MongoDB甚至Solr。您可以存储文档,而无需像使用关系数据库那样设计架构。但是,您失去了架构为您提供的许多结构优势。您最终编写了更多代码来“发现”文档字段,而不是从模式中推断出结构。您没有约束或数据类型或参照完整性。
此外,您可能已经成功地使用关系数据库进行其余的数据管理,并且不能证明同时运行两个不同的数据库是合理的。
关系和非关系极值之间的折衷是Serialized LOB设计,How FriendFeed Uses MySQL to Store Schema-Less Data中描述了扩展。大多数数据都驻留在传统的关系表中。您的无定形表单数据会以一种格式进入单个BLOB列,这些格式将字段和数据一起编码(例如,XML或JSON或YAML)。然后,对于您想要搜索的数据的任何字段,创建一个辅助表来索引该单个字段并引用表单数据的行,其中相应字段中的给定值出现。
答案 1 :(得分:2)
您可能需要考虑EAV data model。