如何为多租户应用程序实现用户定义的字段和分组:EAV、固定表模式、NoSQL

12

我在一家SaaS公司工作,任何租户都可以拥有多个联系人列表,每个列表可以存储任意数量的自定义字段联系人,并且该列表中的联系人可以包含任意数量的分组(分组用于对列表中的联系人进行分段)。 每个联系人都有一个必需的字段:电子邮件地址和为其所在列表定义的任意数量的用户定义字段。 我们必须能够根据它们所在的分组和用户定义值找到列表的联系人。 我们必须提供多达30个用户定义字段。 我现在看到解决这个问题的三种方式:

  1. 使用某种EAV(我们尝试像这样做),但它看起来相当复杂。 我们有一个表列表(租户的列表),相关的表 custom_fields,一个相关的表订阅者,存储了订阅者的电子邮件地址列表,表subscriber_custom_data与订阅者 和自定义字段表(存储订阅者的自定义字段的值)相关。

  2. 使用字段表模式。它的描述在此处http://blog.springsource.com/arjen/archives/2008/01/24/storing-custom-fields-in-the-database/。 在这种情况下,我们将使用与自定义字段相关的字段,该字段将在列中存储所有自定义字段,例如有30个列用于存储每个可能的自定义字段的值,以及一个表,该表存储映射的列名称和用户定义字段的名称。它看起来也很复杂。我们至少需要30个索引来通过自定义字段的值进行搜索,还有其他问题。

  3. 使用某种NoSQL数据库,至少用于存储用户定义字段和列表组。 您认为这些数据库可以在这里发挥作用,如果可以,请问如何设计以存储自定义字段和组。

  4. 我尝试了解不同类型的NoSQL,例如文档导向的MongoDb,但我立即看不出它如何帮助解决这个问题。我们可以在这里存储任意属性,但要搜索自定义字段的值,我们需要事先对它们进行索引,因此我们必须知道将拥有哪些自定义字段。

感谢您提供有关此信息的任何帮助。

1个回答

12
如果您希望所有字段始终被索引,可以尝试使用像Apache Solr这样的技术来进行全文索引。Solr的主要目的是作为全文搜索引擎,但它基本上是面向文档的数据库。
以下是其他选项的评论:
  1. EAV不好,我反对使用它。它违反了关系型数据库设计的许多规则,并且无法扩展。我在Stack Overflow上写过很多关于这个问题的文章,请搜索 eav 标签下的我的回答

  2. 你不仅需要30个索引,而是需要高达30阶乘的索引来处理任何可能的索引组合。请记住,您可以创建多列索引,这些类型的索引对支持某些查询非常重要。当然,创建如此多的索引是完全不现实的;您需要创建与您想要优化的查询相匹配的索引。如果您不知道将拥有哪些字段以及针对它们将有哪些查询,那么您就无法进行优化。

  3. 像MongoDB/CouchDB这样的文档导向数据库并不是魔法,无论他们的支持者试图声称它们是多么神奇。它们要求您为快速搜索对文档进行索引,这意味着您需要知道文档的可索引字段。

    运行时创建索引是一个问题,因为它可能需要很长时间,具体取决于要索引多少数据。您将不得不找到一种方法来“离线”运行索引创建(即在单个http请求期间不要让用户等待它),然后在完成时通知他们。

  4. 您应该阅读关于FriendFeed如何使用MySQL存储无模式数据的文章。他们使用一个序列化的LOB,基本上将所有自定义属性组合成一个XML或JSON blob。因此,用户可以随时创建任意数量的额外自定义字段。但是,在给定的自定义字段可以被搜索之前,您需要创建一个引用包含给定值的行的子表。因此,您获得的索引仅与给定用户定义的自定义字段实例的数量一样大。而且您不需要使每个字段都可搜索。


通过我的用例,我将能够知道可索引字段(但仅在运行时)。租户能够定义自己的字段集(从一组预定义的字段描述符中选择和/或添加自己的字段描述符)。因此,在他们添加新字段时,我应该能够触发(稀疏)索引创建。因此,对于这种特定情况,文档导向存储最合适吗? - Costi Ciudatu
关于使用blob,如何删除/编辑自定义字段并在所有实体中反映出来并不清楚。例如,用户可以在其容器中删除一个字段,该字段应在此容器的所有实体中被删除。请告诉我如何删除/编辑自定义字段并在所有实体中反映出来。此外,例如通过使用添加/删除自定义字段应使其可用于使用和过滤。如果发生EAV级联删除,则会发生。一个字段的大小是有限的,很难预测它将达到blob大小的限制。但是很难说nosql是否能带来任何好处。 - Oleg
Bill,你有没有听说过使用NoSQL作为EAV的替代方案? - Oleg
大多数NoSQL数据库也无法满足这个要求。也就是说,删除一个自定义属性并使其更改所有具有该属性的条目。您必须手动更新每个文档。NoSQL数据库与EAV共享问题,即您无法拥有约束或任何保证任何特定属性集存在。但至少当您使用NoSQL时,这些缺陷不会违反任何规则。 :-) - Bill Karwin
是的 - 当需求复杂时(例如,支持每个用户的自定义字段),解决方案就必然会变得复杂。请参阅TANSTAAFL - Bill Karwin
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接