我在我的Web应用程序的完整restyle的开头,我对一个可靠,查询性能良好的数据库设计有疑问,同时完全可以由用户定制(用户不会自定义数据库结构,但应用程序的功能。)
所以,我的实际情况是,例如,一个简单的用户表:
id | name | surname | nickname | email | phone
1 | foo | bar | foobar | foo@bar.com | 99999
多数民众赞成。
但是,假设我的一位客户希望为一位特定用户提供2个电子邮件地址或电话号码。
直到现在,我过去只是在users表中添加列来解决这个问题:
id | name | surname | nickname | email | phone | email_two | phone_two
1 | foo | bar | foobar | foo@bar.com | 99999 | foo@bar.net | 999998
但我不能用新应用程序的版本使用这种方式..之后我会喜欢喝莫吉托,不喜欢costumer的编辑结构调用:)
所以,我认为一个解决方案,人们可以用另一个表来定义海关领域:
id | table_refer | type_field | id_object | value
1 | users | phone | 1 | 999998
2 | users | email | 1 | foo@bar.net
保持用户表不变。
但这种方式有两个问题:
我的目标是让我的客户为应用程序中的几乎所有对象(用户,项目,发票,打印视图,照片,新闻等等)添加尽可能多的自定义字段,假设大多数这些表的分区将被分割(在2个表中拆分,具有3个表和继承层次结构)。
你认为我的方式可以很好,你知道其他更好的,还是我犯了大错? 拜托,现在每个建议都是黄金!
编辑:
我正在寻找的东西可以通过wordpress博客中的'articles-custom-fields'进行简化。 我的目标是让用户定义他需要的新字段,例如,如果我的用户表是上面的那个,并且客户需要一个我没有阻止的字段,比如网站网址,他必须能够以动态方式添加它,不需要编辑数据库结构,只需编辑数据。
我认为2°表(每个对象的maibe 1)可以是一个很好的解决方案,但我还在等待更好的方法!
答案 0 :(得分:4)
正如我在Answer中提到的类似问题,“数据库设计很难。”您将不得不做出哪个更适合您的决定,规范化表并将电话号码和电子邮件地址放入他们自己的表中,使用相关联的JOIN来检索数据,以及额外的参考努力完整性,或者在表中包含一些 n 电子邮件和电话字段,以及需要的“数据混乱”。
数据库设计总是一系列的权衡。您需要查看所有角度,可能会提出一些原型并进行一些分析等。没有“One True Answer™”。
答案 1 :(得分:1)
您提出的模型由两种数据库模式组成:entity-attribute-value table和polymorphic association。
实体属性值在性能和数据完整性部门都有一些非常大的问题。如果您不需要访问查询中的其他属性,则可以将属性值映射序列化为某些标准序列化(JSON,XML)中的文本字段。从数据库设计的角度来看,这不是“纯粹的”,但考虑到你了解权衡,可能是一个很好的实用选择。在postgres上,如果仅限字符串值的限制是可接受的,您还可以使用hstore contrib模块存储键值对以使其在查询中可用。
对于多态关联,您可以通过引入关联表来获得参照完整性:
users attrib_assocs custom_attribs
----- ------------- --------------
attrib_assoc_id --> id <-- assoc_id
... entity_type field
value
为了获得更多的完整性,还要将entity_type添加到主键和相应的外键以及在users表上将entity_type等于'user'的检查约束。
答案 2 :(得分:0)
如果你这样做,你的所有查询都必须加入并使用table_refer列,这会破坏性能,简化查询,硬查询非常困难。
如果您想要多封电子邮件,请将电子邮件拆分到另一个表格,这样您就可以拥有多行。
答案 3 :(得分:0)
您可以根据需要设计应用程序以使用AJAX等请求其他数据(例如用户的电子邮件列表)。在那些高度可定制且丰富的应用程序中,通常您无需显示所有数据 - 只需一个类别。
要存储自定义记录,您可以创建表field_types(id, name, datatype)
和表custom_fields(user_id, field_type_id, value)
,然后选择这样的smth:
SELECT * FROM custom_fields WHERE user_id=XXX AND field_type_id IN (X,Y,Z)
。
现在您可以在1个快速查询中检索数据,将字段拆分为类别,并使用您的代码按照各自的数据类型解析它们的值,而不会出现性能问题。
答案 4 :(得分:0)
我不确定postgresql的具体细节,但是如果你想在数据库中使用高度可自定义的数据结构,你真的不想搜索,那么s erializing the data to a LOB是一个选项。
实际上,这是ASP.NET默认使用Personalization的方式,即按用户设置。
如果您因任何原因希望搜索字段,我不建议使用此方法。