我正在为在线业务管理系统在 Postgres 中设计一个数据库。在这里,我有两个选择:
- 拥有一个包含所有客户数据的数据库,并在所有表中添加带有客户 ID 的列以仅过滤其数据。
- 每个注册的客户都有自己的数据库,其中只有他们的数据。
第二个选项对我来说似乎更有序,因此不会在同一个表中混合来自不同客户端的数据。在我看来,如果必须在较小的表中查询,数据库的性能会更好,但这只是一个猜测,因为同时查询了许多数据库,我不知道引擎是否会降低它的表现。
查询是,假设客户数量增加,并且您选择每个客户拥有自己的数据库,
Postgres 可以处理的数据库数量是否有限制?关于性能?
查询多个小型数据库是否比查询单个大型数据库更好?
看,现在告诉 Linux 机器它可以保持数百万个文件打开是微不足道的,因此本身作为文件存在的表的数量不是问题。此外,Postgres 在内存中保留有限数量的数据,除此之外,还有有限数量的页面(表中的数据段、索引、序列等)
visibles
。但是,在文件系统下,
ext4
您最多只能处理 64,000 个子目录。这意味着您可以拥有 63,995 个数据库。其他5个是.
指向当前子目录的硬链接..
到父子目录的硬链接postgres
默认模板template1
替代模板 1template2
替代模板 2如何绕过这个限制?
如果您使用dir_nlink指令,您可以使硬链接实际上不计入此限制。出于同样的原因,您可以使您的一些数据库实际上不在 postgres 目录下,而是在 postgres 通过硬链接指向的另一个子目录中。
但是您不必对此感到复杂。Postgres 本身支持可以物理驻留在磁盘上其他位置的表空间。
战略方针
尽管实现 struct 并不罕见
multitenant
,但它在很大程度上取决于您要存储的数据。无论是在数量上还是在保密程度上,您可能不必将所有内容存储在一起。更重要的是,当您实施多租户系统时,如果有一天您想将数据分离到不同的数据库中,那么分离数据几乎是不可能的。如果您使用不同的数据库,则必须实现一种实例注册表,将客户端与其数据库实例(可以使用 tuple 完成
cliente-PGurl
)链接到其他地方。在该方法convención por sobre configuración
中,客户端的净化名称可以映射到数据库的名称。但是有一天你会想要在不同的机器上拥有不同的客户端,而这种方法对你没有用。正如我之前所说,隐私和安全法规取决于业务类型,特别是如果您想在 ISO 27001 中认证自己(让我们考虑一下),您必须实施比混合所有内容更强大的东西。多租户对于多租户系统来说是完美的,但对于多租户系统来说却不是那么完美。
表现
根据您正在考虑的表的大小,如果将所有内容都放在同一个数据库中,则不利用索引的查询的性能可能会降低。但是如果索引和查询设计得很好,这种损失将是微不足道的。此外,通过 Postgres 10 中内置的分区并在 Postgres 11 中进行了改进,您可以使用循环分区来解决该问题。对于任何具有键的表
cliente_id
(如您在多租户替代方案中所述),您可以通过以下方式按哈希进行分区:根据大数定律,记录将或多或少地平均分为 3 个。Postgres 11 以这样一种方式优化查询,即在执行查询时,它会尽可能早地忽略无法匹配查询的分区。
无论您使用大型数据库还是许多数据库,拥有许多连接的客户端都意味着在内存中保留大量数据和大量可见数据,这两种情况都会发生。
区别在于战略方面。如果事先分离并实现了实例注册中心,以后可以通过增加更多的机器来横向增长,而不是让主机变胖。
那个,最后是同一个篮子里的鸡蛋的古老格言......
Bonus Track:通过业务层映射
我曾经实现了一个系统,其中的绊脚石不是关系结构,它符合 3NF。事实上,客户可以上传 N 个包含任意列的数据表,这些列是他的“个人收藏”,就像有人将电子表格上传到谷歌驱动器一样。
pg_tables
由于无法使用 postgres 目录实体(如 您必须使用业务层将客户与其表相关联,并在删除客户之前将其删除。因此,业务层与持久层是绝对耦合的,其思想是应用程序的各层不需要知道超过最低限度的相邻层的实现。
(目前有人会告诉我,我没有每个客户有 N 个表,而是有一个表,其中每条记录都有一个 JSONB 类型的字段,其中包含该行所有者的特定数据集合......这几乎没问题,除了这些是需要使用 PostGIS 过滤的地理空间表(Postgres 没有像 MongoDB 这样的 GeoJSON 结构的空间索引)