PostgreSQL 11:如何对 1000 个租户进行分区

Ale*_*aru 5 postgresql partitioning

设置

我们有一个多租户应用程序,大约有 1000 个客户。当客户流失时,我们会在一段时间后删除他们的所有数据。我们有一些非常大的表,我们正在考虑使用分区来按客户拆分它们。

问题

1000 个租户(客户)是很多分区 - 在 PostgreSQL 上这样做合理吗?

更多细节

目前,我们的租户之间的分离是通过account_id数据库中所有表上的列来实现的。有几张桌子都很大。例如,有一个event表(我对分区感兴趣的表)包含审核日志和我们应用程序中发生的所有事件的其他事件。

以下是有关事件表的一些事实:

  • 它包含大约 300M 行+一些复合/部分索引。
  • 事件计数account_id非常不均匀,5% 的帐户拥有 50% 的数据。
  • 有一个时间戳字段和其他一些字段(JSONB,author_id等等)
  • 写操作:主要插入和删除(每account_id)。删除的数据可能有数百万行。没有更新。删除大帐户的情况很少见,目前并不是一个大的性能问题。
  • 选择特定事件(通过account_id+ id)或给定时间段内的所有事件。并不总是设定时间段。account_id始终出现在查询中。

可能的解决方案

分区方式account_id

优点:

  • 删除速度会很快,因为DROP TABLE.
  • 查询也应该相当不错,因为所有查询都包含WHERE account_id = 123

缺点:

  • 1000 个分区对于 Postgres 来说太多了吗?
  • 每个帐户的事件分布不均匀,创建了一些超大分区和一些小分区。

按时间戳分区:

优点:

  • 最近的数据通常会被访问,并且会使带有时间戳的查询更快。
  • 事件的分布更加可预测/均匀。

缺点:

  • 删除单个帐户可能会触及很多分区 - 这不是一个大问题。
  • 始终需要包含按时间戳的过滤器 - 这并不总是可能的。

Lau*_*lbe 5

分区主要是为了加快删除和顺序扫描的速度。

  • 如果您最大的痛苦是 的大量删除account_id,则该列上的列表分区将是最好的解决方案。

  • 如果您最大的痛苦是删除早于某个日期的所有数据,那么按时间进行范围分区将是解决方案。

  • 如果您有多个查询必须对大型表执行顺序扫描,但有条件WHEREaccount_id时间限制,则根据该WHERE条件进行分区将允许 PostgreSQL 仅对某些分区执行顺序扫描。

您必须确定这些事情是否足以让您考虑分区。分区并不是免费的:它会增加查询计划时间,有时还会增加执行时间。

分区不会使索引扫描更快,通常情况恰恰相反。仅当您希望从中获得真正的好处时才进行分区。

1000 个分区几乎太多,效率低下。您可能会考虑为较大的帐户设置单独的分区,并将其余帐户捆绑在一起,也许使用默认分区。