可以在“table_name_prefix”中指定模式吗?

Is it OK to specify a schema in `table_name_prefix`?

TL;DR:可以在 table_name_prefix 中指定模式吗?

我们有一个大型 Rails 应用程序,它不完全是传统的多租户应用程序。我们有一百个客户,所有客户都由一个应用程序支持,而且这个数字每年的增长永远不会超过 1-2 个。目前,每个客户端都有自己的 Postgresql 数据库。

我们正在解决因拥有如此多不同的数据库而引起的一些基础设施问题...最紧迫的是,在同时处理许多客户端数据时同时存在大量数据库连接。

该应用程序是不可见的,即使对客户也是如此,因此许多传统的多租户网站理念在这里并不适用。

每个租户的 table 差异很大。没有希望或希望使客户一起正常化。客户端不是动态配置的——它始终是带有迁移的新代码版本。

我们打算将每个客户端模式移动到一个数据库中,因此需要更少的不同连接池。我们目前在数据库、模式和 table 名称中拥有的唯一名称意味着不存在名称冲突的可能性。

我们查看了公寓 gem,并认为它不适合我们正在做的事情。

我们可以将所有一百个模式添加到 schema_search_path,因此所有客户端都可以共享同一个连接池并且仍然可以找到它们的模式。我们相信这会将我们的数据库连接数减少一百倍。但我们对此有点不安。我没有发现有多少是太多的讨论。也许这会奏效,也许不会有性能损失发现 tables.

通过在 table_name_prefix 中添加模式,我们找到了一个看起来很有希望的非常简单的解决方案。我们已经这样设置了:

def self.table_name_prefix
  'client99_'
end

通过在 Rails 4(我们的当前版本)和 Rails 5 源代码中进行试验和查看,这可以指定架构 ('tenant_99') 以及传统的 table 前缀 ('client99') :

def self.table_name_prefix
  'tenant_99.client99_'
end

在此更改之前,查询如下所示:

SELECT COUNT(*) FROM 'client99_products'

之后,他们根据需要包含架构:

SELECT COUNT(*) FROM 'tenant_99.client99_products'

这似乎满足了我们的需求,没有任何缺点。我在 Interwebs 上搜索过鼓励或反对这种做法的人,但没有发现任何提及。

所以通过所有这一切,以下是我还没有找到明确答案的问题:

以相反的顺序解决您的问题:

  • 将架构名称放入 table_name_prefix 可以吗?

只要名称是唯一的(内部和外部)就没有问题。

  • 是否担心 schema_search_path 中列出的架构过多?

答案可能是,任何 non-fully 符合条件的请求(仅按名称请求 table)都必须按照 schema_search_path 中列出的顺序搜索每个模式 如果它缓存在内存中,几乎没有损失; on-disk 搜索所有模式会很慢(与其在列表中的位置成正比。) 请务必首先列出最活跃的模式。

完全合格的请求不应比分离的数据库解决方案花费的时间更长。

假设您的所有调用都是完全合格的,此技术应尽可能提供连接池的全部优势。

请记住,连接池仅通过在通信期间利用 "gaps" 来最大限度地减少设置开销和连接的 tear-down 次。

例如:

  • 你有四个客户端,其中三个几乎不断发出请求,你仍然有四个到服务器的连接,即使有池。

  • 当您有四个客户端,每个客户端使用四分之一的资源,通过单个连接汇集时,优势就来了。

基础(不包括连接开销)数据库利用率将保持不变,无论是与单个数据库合并还是与单独数据库的单独连接。

将数据库合并为一个数据库的 drawback/advantage 是这样的:除了 PostgreSQL 的负载平衡方法之外,不可能将单个数据库移动到另一台服务器以实现负载平衡。