在postgresql中,分区或多个数据库更高效吗?

时间:2011-12-08 14:36:55

标签: postgresql partitioning

有一个应用程序,许多公司发布信息。每家公司的数据都是自包含的 - 没有数据重叠。

表现方面,是否更好:

  • 在每个表的每一行上保留公司ID并让每个索引使用它吗?
  • 根据公司ID
  • 对每个表进行分区
  • 分区并创建用户以访问每家公司以确保安全性
  • 创建多个数据库,每个公司一个

具有持久连接的基于Web的应用程序。

我的想法:

  • 新的pg连接很昂贵,因此单个数据库创建的连接较少
  • 只有一个字典副本似乎比200左右更有效
  • 多个数据库肯定比程序员错误更安全
  • 如果应用程序规范应该更改,那么公司共享多个数据 基数难以实施

1 个答案:

答案 0 :(得分:15)

我建议在PostgreSQL邮件列表中搜索有关多租户设计的信息。那里有很多讨论,答案归结为“它取决于”。在保证隔离,性能和可维护性之间存在各方面的权衡。

一种常见的方法是使用单个数据库,但每个客户使用一个schema(命名空间),每个模式中具有相同的表结构,以及所有数据中相同的数据的共享或公共模式。 PostgreSQL模式就像一个MySQL“数据库”,您可以跨不同的模式进行查询,但默认情况下它们是隔离的。通过单独架构中的客户数据,您可以使用search_path设置,通常是ALTER USER customername SET search_path = 'customerschema, sharedschema',以确保每位客户都能看到他们的数据,只看到他们的数据。

为了获得额外的保护,您应该REVOKE ALL FROM SCHEMA customerschema FROM public然后GRANT ALL ON SCHEMA customerschema TO thecustomer这样他们就是唯一一个可以访问它的人,对他们每个人都做同样的事情。表。然后,您的连接池可以使用对任何客户架构具有 GRANT访问权限的固定用户帐户登录,但有权SET ROLE成为任何客户。 (通过向NOINHERIT设置每个客户角色的成员资格来实现这一点,因此必须通过SET ROLE明确声明权利)。该连接应立即SET ROLE给它当前正在运营的客户。这样可以避免为每个客户建立新连接的开销,同时保持对程序员错误的强大保护,从而导致访问错误的客户数据。只要池在将连接交给下一个客户端之前执行DISCARD ALL和/或RESET ROLE,这将为您提供非常强大的隔离,而不会让每个用户的个别连接受挫。

如果您的Web应用程序环境内置了一个不错的连接池(比如说,您使用的是持久连接的PHP),那么真的需要放置一个good connection pool无论如何,在Pg和Web服务器之间就位,因为与后端的连接太多会损害您的性能。 PgBouncerPgPool-II是最佳选择,在联系切换期间,您可以轻松地为您执行DISCARD ALLRESET ROLE

这种方法的主要缺点是维护许多表的开销,因为为每个客户克隆了基本的非共享表集。随着客户数量的增长,它会加起来,在autovacuum运行期间要检查的表的数量开始变得昂贵,并且根据数据库中的表总数进行扩展的任何操作都会减慢。如果您考虑在同一个数据库中拥有数千或数万个客户,那么这就更成问题了,但我强烈建议您在提交之前使用虚拟数据进行一些缩放测试它。

理想的方法可能是具有自动行级安全性控制元组可见性的单个表,但不幸的是PostgreSQL还没有。由于SEPostgreSQL工作添加了合适的基础架构和API,它看起来还在路上,但它不在9.1中。