繁体   English   中英

如何构建一个完全可定制的应用程序(又名数据库)而又不损失性能/良好的设计?

[英]How to build a fully-customizable application (aka database), without lose performance/good-design?

我是在完全重新设计我的Web应用程序的开始,我对良好的数据库设计存有疑问,该数据库设计可以可靠,具有查询性能,并且可以由用户完全自定义(用户不会自定义数据库)结构,但应用程序具有功能性)。

因此,我的实际情况是,例如,一个简单的用户表:

id | name | surname | nickname | email       | phone
1  | foo  | bar     | foobar   | foo@bar.com | 99999

而已。

但是,可以说我的一位客户希望为一位特定用户拥有2个电子邮件地址或电话号码。

到目前为止,我以前只是通过在用户表中添加列来解决该问题:

id | name | surname | nickname | email       | phone | email_two    | phone_two
1  | foo  | bar     | foobar   | foo@bar.com | 99999 | foo@bar.net  | 999998

但是我不能在新应用程序的版本中使用这种方式。.在那之后,我想喝莫吉托鸡尾酒,不喜欢客户打电话来编辑结构:)

因此,我想到了一个解决方案,人们可​​以仅通过另一个表来定义海关字段:

id | table_refer | type_field | id_object | value
1  | users       | phone      | 1         | 999998
2  | users       | email      | 1         | foo@bar.net

保持用户表不变。

但是这种方式有两个问题:

  1. 据我所知,不可能以这种方式使用外键,即如果我删除1个用户,则外键会自动级联删除第二个表中所有具有'table_refer'value = users和id_object = users.id。 当然,我可以使用一些触发器功能,但是我会失去一些可靠性。
  2. 当我需要查询数据库时,要检索与“ foo@bar.net”匹配的用户,我还必须检查所有... hem .. option_table,这将使我的代码变得复杂和可靠性不高,并且有很多连接的麻烦。.假设users表不是'option_table'唯一的'扩展'表,似乎是一个灰色视图。

我的目标是让我的客户为应用程序中的几乎所有对象(用户,项目,发票,打印视图,照片,新闻等)添加所需数量的自定义字段,假设其中大多数表将被分区(拆分为2个表,具有3个表和继承体系)。

您认为我的方式可以很好,您知道其他更好的方法,还是我犯了个大错误? 请,每个建议现在都是金子!

编辑

我要寻找的内容可以通过wordpress博客中的“文章-自定义字段”来简化。 我的目标是让用户定义他需要的新字段,例如,如果我的用户表位于上方,而客户需要我没有阻止的字段(例如网站url),则他必须能够动态地添加它,无需编辑数据库结构,而只需编辑数据即可。

我认为2°工作台(每个对象1个)可以是一个很好的解决方案,但我仍在等待更好的方法!

就像我在回答类似问题时所说的那样,“数据库设计很难。” 您将不得不决定哪个更适合您,将表格标准化并将电话号码和电子邮件地址放入自己的表格中,并使用关联的JOIN-ing来检索数据,并付出额外的精力进行引用完整性,或表中有一些n电子邮件和电话字段,以及随之而来的“数据混乱”。

数据库设计始终是一系列折衷。 您需要从各个角度进行研究,也许需要整理一些原型并进行一些分析等。没有“ One True Answer™”。

您提出的模型由两种数据库模式组成: 实体-属性-值表多态关联

实体属性值在性能和数据完整性部门中都存在一些相当大的问题。 如果您不需要访问查询中的其他属性,则可以将属性值映射序列化为某些标准序列化(JSON,XML)中的文本字段。 从数据库设计的角度来看,这不是“纯粹的”,但考虑到折衷,这可能是一个不错的实用选择。 在postgres上,如果仅字符串值的限制是可接受的,则还可以使用hstore contrib模块存储键值对以使其在查询中可用。

对于多态关联,可以通过引入关联表来获得引用完整性:

users                attrib_assocs       custom_attribs
-----                -------------       --------------
attrib_assoc_id -->  id             <--  assoc_id
...                  entity_type         field
                                         value

为了获得更高的完整性,还需要将entry_type添加到主键和相应的外键上,并在用户表上添加检查条件,以使entity_type等于“ user”。

如果以这种方式执行此操作,则所有查询都必须加入并使用table_refer列,这会降低性能,并使简单查询变得困难,而使困难查询变得非常困难。

如果您需要多封电子邮件,请将电子邮件拆分到另一个表中,这样可以有很多行。

您可以设计应用程序以使用AJAX等按需请求其他数据(例如用户的电子邮件列表)。在那些高度可定制且功能丰富的应用程序中,通常无需显示所有数据-仅单个类别。

要存储自定义记录,您可以创建表field_types(id, name, datatype)和表custom_fields(user_id, field_type_id, value) ,然后选择以下方式:

SELECT * FROM custom_fields WHERE user_id=XXX AND field_type_id IN (X,Y,Z)

因此,现在您可以在1个快速查询中检索数据,将字段拆分为类别,并使用代码按其各自的数据类型解析其值,而不会出现性能问题。

我不确定postgresql的具体细节,但是如果您想要数据库中高度可定制的数据结构,而您实际上并不想在其中进行搜索,则可以将数据序列化为LOB

实际上,这是ASP.NET默认情况下与Personalization(按用户设置)一起工作的方式。

如果您出于任何原因要搜索字段,我不建议您使用这种方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM