在“ table_name_prefix”中指定架构可以吗?

Dav*_*mpy 6 postgresql activerecord ruby-on-rails

TL; DR:是否可以在中指定架构table_name_prefix

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

我们正在解决一些基础结构方面的问题,即拥有这么多不同的数据库……最紧迫的是,在同时处理许多客户端数据时,存在大量并发数据库连接。

该应用程序甚至对客户都不可见,因此许多传统的多租户网站理念在这里并不适用。

  • 每个租户都有一个单独的Postgres数据库,由database.yml管理。
  • 每个数据库都有一个以租户命名的模式。
  • 我们有一个针对每个租户的特定模型,其代码明显不同。
  • 每个模型都使用Establishment_connection选择不同的数据库和模式。
  • 每个模型都使用一个table_name_prefix与客户的唯一名称不同的名称。

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

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

我们查看了Apartment的宝石,并确定它不适合我们正在做的事情。

我们可以将所有一百个模式添加到schema_search_path中,以便所有客户端可以共享同一连接池,并且仍然可以找到其模式。我们认为,这将使数据库连接数减少一百倍。但是我们对此有些不安。我还没有讨论过多少。也许那会行得通,也许不会有性能损失查找表。

通过在table_name_prefix中添加架构,我们找到了一个非常有前景的简单解决方案。我们已经将其设置为:

def self.table_name_prefix
  'client99_'
end
Run Code Online (Sandbox Code Playgroud)

通过在Rails 4(当前版本)和Rails 5源代码中进行试验和查看,可以指定模式(“ tenant_99”)以及传统的表前缀(“ client99”):

def self.table_name_prefix
  'tenant_99.client99_'
end
Run Code Online (Sandbox Code Playgroud)

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

SELECT COUNT(*) FROM 'client99_products'
Run Code Online (Sandbox Code Playgroud)

之后,根据需要包含模式:

SELECT COUNT(*) FROM 'tenant_99.client99_products'
Run Code Online (Sandbox Code Playgroud)

这似乎满足了我们的需求,没有任何缺点。我在Interwebs上搜索了鼓励或劝阻这种做法的人,但没有找到任何提及的方式。

因此,通过所有这些,以下是我尚未找到明确答案的问题:

  • 是否担心其中列出了太多的架构schema_search_path
  • 可以放置架构名称table_name_prefix吗?

小智 2

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

  • 将模式名称放在 table_name_prefix 中可以吗?

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

  • 是否担心列出了太多模式schema_search_path

答案可能是,任何非完全限定的请求(仅通过名称请求表)都必须按照中列出的顺序搜索每个模式。schema_search_path如果将其缓存在内存中,则几乎没有惩罚;对所有模式的磁盘搜索将会很慢(与其在列表中的位置成正比)。请务必首先列出最活跃的模式。

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

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

请记住,连接池只是通过利用通信期间的“间隙”来最大限度地减少连接建立和拆除时间的开销。

例如:

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

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

无论是与单个数据库进行池化还是与单独数据库的单独连接,底层(不包括连接开销)数据库利用率将保持不变。

将数据库合并为一个数据库的缺点/优点是:不可能将单个数据库移动到另一台服务器以实现 PostgreSQL 负载平衡方法之外的负载平衡。