【问题标题】:MySQL User Defined Values - EAV vs Sharding with Many tablesMySQL 用户定义值 - EAV 与多表分片
【发布时间】:2013-02-19 08:07:09
【问题描述】:

我目前正在开发一个多租户系统,该系统的核心功能允许用户定义自定义类型。例如,他们将定义一个事件、帐户、订单、发货,无论他们选择什么。系统中的每个用户都将根据字段对他们想要管理的内容有不同的定义。因此,对于一个用户,一个订单可能有一个订单号、状态和截止日期,而对于另一个用户,它可能有 10 个字段。

与我合作的开发人员希望使用 EAV 来存储这些数据。我反对这个想法。我已经阅读了这个网站以及整个互联网上的许多文章,列出了这种反设计模式的缺点,但没有提到我正在考虑采用的方法。我正在尝试构建这个应用程序,使其从一开始就具有可扩展性。

当我做数学时,如果我有 1000 个租户,每个租户平均有 5 种类型(5000 种类型)。例如,每种类型都有 1000 条记录(5,000,000 条记录)。每条记录平均有 5 个字段,在 EAV 模型的最低级别,我总共有 25,000,000 行。

下游流程还将每个单独的用户数据绑定到一个 jquery 网格,所以首先获取这些数据并转置数据对我来说似乎成本很高。当你有 10k 租户或 50k 租户时会发生什么......我知道 MySQL 可以在优化后处理这种类型的事情,但是这似乎就像我在踢自己的脚。

我想换一种方式。然而,我对我的提议有一种不好的直觉,因为它违背了我所知道的一切,所以我希望一些真正的具有实践知识的专家来验证或批评我的方法。如果您验证,请告诉我我需要做些什么来支持它并让它工作。如果你批评,请告诉我我在短期和长期会遇到的陷阱。

我的建议。

  1. 使用域分区对系统进行分片,以便在任何特定分片中都有最大的租户集。主目录将引用哪个租户属于哪个分片
  2. 对于每个 Shard,当用户定义一个类型时,创建一个新表来保存该类型。在分片中保存一个映射表,它将用户链接到他定义的类型(自定义表)。

这实质上意味着我将在一个分片中拥有少量核心表和 1000 个自定义表。

现在对我来说,通常在数据库中有这么多表通常会告诉我架构有问题或设计不正确,但是对于这种情况,我只是想知道它是否是可行的办法。在我之前的示例中,这意味着我在分片中有 5000 个表,每个表只有 1000 行。在我看来,这似乎比使用 EAV 更好。根据用户,您找到类型并将数据绑定到网格。

需要考虑的一些注意事项

  1. 多租户架构允许用户拥有自己的用户。所以可能我有 1000 个订阅者,但有 5000 个用户。所以需要管理数据库连接。我会在管理连接时遇到问题吗?

  2. 我会遇到与表缓存相关的问题吗?刷新表会不会有问题?

  3. 此设计可能会遇到哪些性能问题?我知道主目录数据库可能是一个瓶颈,但是这个数据库的负载不会太重。

  4. 已经开始开发了,别叫我换NoSQL数据库!

另一个建议是在分片内继续使用 EAV。您如何看待这个想法?

请不要出拳!我需要听到这一切。 提前致谢。

【问题讨论】:

  • EAV 在查询数据时很麻烦(就像您想要的网格一样!),但它支持您正在寻找的通用基础架构。根据您的域,是否可以跨租户共享“事件”表架构? (与“帐户”、“订单”、“发货”等相同)?这样做的缺点是,由于它们的大小,扩展表很快就会变得不可能(我们又回到了 EAV!)。
  • 不幸的是,除了将相应分区的公共表之外,租户之间不会有共享模式。想到将 EAV 数据绑定到网格的下游过程真的让我很反感。

标签: mysql multi-tenant saas sharding entity-attribute-value


【解决方案1】:

我认为在扩展数据方面,您会发现管理数千个相对较小的自定义表会比使用 EAV 做得更好。我曾为在单个 MySQL 实例上拥有超过 100,000 个表的客户提供咨询。

当您在一个实例上拥有数以万计的表时,您会遇到不同的可扩展性问题,但如果您已经拥有支持分片的架构,您就可以进一步细分用户,这样您就没有任何一个实例都太多了。

目录表非常适合放入缓存(例如 memcached),因为用户到分片实例的映射很少更改。这将减少目录的负载。

我还会研究 MySQL 的目录分区,以及将用户映射到他们的自定义表的表。以及任何其他常见(非自定义)表。您可以按用户 ID 对其中任何一个进行分区,并依靠分区修剪来使多租户表表现得像小得多的表。

【讨论】:

  • 感谢您对此法案的回复,我希望能得到您的回复。在发布这个问题之前,我阅读了很多你的反 EAV 文章。您基本上证实了我最初对管理许多自定义表而不是 EAV 模型的怀疑。我相信我要做的就是限制分片中的租户,这样表数就不会变得不堪重负。如果我说绝对最大值为 20k 表(更可能是 10k),我可能会遇到哪些不同的可扩展性问题?
  • 根据查询模式,您可能需要增加table_cache_size。它的默认值很小:64。当他们有很多表时,我已经看到站点将其增加到 1000-4000 甚至更高。但在某些情况下,将其提高得太高会导致性能下降,因此请务必在调整此类之前和之后测量您的性能。
猜你喜欢
  • 1970-01-01
  • 2011-06-07
  • 2018-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多