PostgreSQL 在处理大量数据库时的表现如何?

Car*_*elo 9 postgresql database-administration database-performance

我们有一个 Web 应用程序,其架构要求任何注册用户(实际上是一家公司)都应该彼此隔离,即,我将使用相同的数据模型运行相同的 Web 应用程序,但为每个客户使用不同的数据集。

所以,我们确实考虑过在 Postgres 中为每个客户创建一个不同的数据库。这个解决方案可以扩展到 10-20K 的数据库吗?多好?

有没有人对此有更好的解决方案?

提前致谢。

Der*_*rfK 11

在低端,基本上归结为“你能绝对说你没有共享数据吗?” 与 mysql 不同,数据库在 postgresql 中是一个绝对的边界。你不能SELECT zip_code FROM common.city_zip WHERE city=...,如果你去与不同的数据库中(至少在没有dblink)。

如果您有任何共享数据,postgresql 的“模式”类似于 mysql 所谓的“数据库”。你可以CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);。您将为每个客户端创建一个架构,该客户端的用户将首先在其搜索路径中拥有他们的架构,并且将授予权限,以便客户端 A 的用户可以访问clientapublic架构(及其表)。

您的问题将是在客户端数量的高端,每个表都存储为一个文件,因此无论您为每个客户端使用一个数据库,每个客户端使用一个架构,还是使用类似${client}_customer的名称作为表名,您都将即使每个客户端只有一张表(每个连接加上一个文件描述符),也可能会遇到10k 客户端的文件描述符限制。当然,您可以使用 sysctl 动态调整内核的最大文件描述符数量,但是如果您第一次将每个进程的限制 (ulimit) 设置得太低,则需要重新启动 postgresql。

另一种方法是使用“一个大表”,其中包含一个客户端列,用于标识该行属于哪个客户端(理想情况下,如果每个客户端有一个用户,则通过用户名,这使得下面的内容更容易)。通过不授予客户端对此表的任何访问权限,您可以创建特定于客户端的视图(或用于session_user标识当前客户端)。但是,不能直接通过视图进行更新。您需要定义在表上插入/更新/删除的函数(每个客户端一组函数或使用其他session_user函数),这些函数SECURITY DEFINER用于作为特殊用户执行,并有权在表上插入/更新/删除(注意:session_user使用是因为usercurrent_user 以当前上下文为基础,并且在 SECURITY DEFINER 函数中,这将始终是定义函数的用户)。

在性能方面,除了 fd 问题之外,老实说,我不知道 postgresql 中的 10000 个数据库会发生什么,而不是拥有一个包含 10000 个客户的数据的大表。适当的索引设计应该可以防止大表查询缓慢。

我会说我在这里为每个客户端使用了单独的数据库(我们添加服务器以保持系统可用,根据需要将客户端数据库转移到新服务器,因此我们永远不会在一台服务器上获得 10k 数据库)。我不得不定期从备份中恢复单个客户端的数据以进行调试或由于用户错误而定期,这对于“一张大表”设计来说绝对是一场噩梦。此外,如果您打算向您的客户销售您的产品定制,“一张大桌子”设计最终可能会阻碍您定制数据模型的能力。