从 Postgres 表中删除数百万行的自动化方法

Automated way of deleting millions of rows from Postgres tables

Postgres 版本:PostgreSQL 10.9 (Ubuntu 10.9-1.pgdg16.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609, 64-bit

在我提出问题之前,我想解释一下我为什么要调查这个问题。我们有一个历史 table,它有超过 500 万行并且每小时都在增长。

随着 table 长度的增长,select 查询变得越来越慢,即使我们有一个合适的索引。所以理想情况下我们的首选是删除未使用的旧记录。

方法 #1

我们尝试使用简单的 delete from table_name where created_date > certain_date where is_active = false

从 table 中删除记录

方法 #2

创建一个脚本,使用基于游标的方法删除行。

方法 #3

在现场制作实例中,这会导致数据丢失/导致故障

方法 #4

经进一步调查,删除未使用行的高效方法是创建一个 table 分区 https://www.postgresql.org/docs/10/ddl-partitioning.html - 我们可以立即删除整个分区。

上述方法的问题是

  1. 如何在现有 table 上创建分区?
  2. 这需要停机吗?
  3. 我们如何配置 Postgres 自动创建分区,我们不能每天手动创建分区吧?

也欢迎任何其他方法,问题是我真的希望这是自动化的而不是手动的,因为我会将其扩展到多个 tables。

请告诉我你的想法,这将非常有帮助

我会选择方法 4,table 分区。

  1. 创建分区
  2. 新数据直接进入正确的分区
  3. 将旧数据(手动/脚本)移动到正确的分区
  4. 设置一个 cron 作业来为接下来的 X 天创建分区,如果它们不存在的话

无需停机

We tried deleting the records from the table using simple delete from table_name where created_date > certain_date where is_active = false This took a very long time.

你肯定是指 <,而不是 >?那么,如果需要很长时间呢?你需要多快?它造成问题了吗?您尝试一次删除多少数据?

500 万行很小。我可能一开始就不会在这么大的东西上使用分区。

如果您还没有分区数据,则没有简单透明的方法可以迁移到分区数据。最简单的方法是在填充新 table.

时稍作休息

如果您确实想要分区,您的分区方案必须包括 is_active,而不仅仅是 created_date。白天似乎太好了,你可以按月做,然后预先创造几年的价值。

具体回答以下内容:

How can we configure Postgres to create partition automatically, we can't really create partitions manually everyday right?

由于您使用的是 Postgres 10,您可以使用 https://github.com/pgpartman/pg_partman 自动管理分区。