基于日期的最佳 Postgres 分区

Optimal Postgres partitioning based on date

我正在寻找改进 Postgres(分区)tables 中数据删除的方法,而不是降低访问性能。

使用:Postgres 10.2

忽略一些不相关的列,我有 table transactions 这些列(省略一些不相关的列):

transaction_id PK
location
type
user_id
transaction_date

关于当前table的一些要点:

  1. 在生产中,它有大约 1 亿行
  2. table 基于 user_id(模 100)进行(手动)分区。这意味着具有 user_id 3 的用户的交易将转到 transactions_3user_id 2356 将转到 transactions_56
  3. 我们手动插入记录,因为 Postgres(10) 不支持这种开箱即用的分区,因为我们已经知道必须为其插入事务的用户(也是在检索时)

什么效果好:插入和检索,因为我们已经知道用户 - 我们知道要查看哪个 table,因此不必经过找到它的 100 个分区。

什么没有:我们有一个经常删除旧数据的过程 - 基于用户订阅。但这通常会导致问题(space 问题),因为删除的数据不会立即释放。当 table 由于大量更新或删除 activity 而包含大量死行版本时,普通的 VACUUM 可能不够用(就像我们这里的情况)

我们希望如何改进这一点,以便能够根据交易日期将数据存储在分区中 - 然后能够在订阅结束时删除 tables。这将确保 space 可以立即再次使用。

简而言之,我们的主要目标是改进删除过程,以便立即恢复 space - 同时确保访问性能不会恶化

关于这个我有几个问题:

  1. 如果我们根据日期对 table 进行分区,我认为这(至少访问)会变慢,因为它现在必须扫描所有 100 个 table 才能看到交易 ID 在哪里?
  2. 是否真的有可能实现这一点,保持交易的检索像以前一样 - 同时改进删除过程。如果可以,怎么做?
  3. 我认为在日期和帐户上进行分区并不是真正的 possible\good 解决方案 - 因为可以创建大量的 table? (需保留数据最长2年)
  4. 为此,我们是否需要迁移到更新的 Postgres,比如说 Postgres 14(它是最新的)。我知道升级到最新版本总是好的。但我想知道 - 是否真的可以在不升级 Postgres 的情况下做到这一点。

希望在前进的道路上得到一些指导。

首先:升级 PostgreSQL 是一个非常好的主意,不仅因为散列分区是在 v10 之后引入的,而且因为自 v10 以来分区的性能和功能有了很多改进。

我感觉您现在使用的分区方案(自行开发的散列分区)对您帮助不大。您无法用简单的 DROP TABLE(这会很好)来摆脱客户,并且在一个分区中删除 1000 万行并不比在一个大的 table 中删除它们更有趣。相反——一旦完成 autovacuum,相对膨胀会更多。唯一的优点是 autovacuum 会更有效地工作,因为它可以单独处理每个分区。

回答您的问题:

  1. 是的,分区会使大多数查询变慢;希望不会慢很多。这就是你付出的代价。

  2. 不,您的查询会变慢一些(与分区数成正比,所以保持适度)。

  3. 您可以根据这两个标准进行分区,因为一个分区可以再次被分区 table。但我怀疑这是否真的是个好主意,因为我怀疑您当前的分区方案是否真的有用。

  4. 是的,至少使用 v12,最好是 v14。