删除大型 postgresql 数据库表中的重复行
Posted
技术标签:
【中文标题】删除大型 postgresql 数据库表中的重复行【英文标题】:delete duplicate rows in large postgresql database table 【发布时间】:2013-07-25 07:52:09 【问题描述】:我有一个 100 GB 大小的 postgresql 数据库。其中一张表有大约十亿个条目。为了快速输入数据,一些数据被重复并留待以后修剪。其中一列可用于将行标识为唯一的。
我找到了this *** question,它为 mysql 提出了一个解决方案:
ALTER IGNORE TABLE table_name ADD UNIQUE (location_id, datetime)
postgresql 有类似的吗?
我尝试使用 group by 和行号删除,在这两种情况下,我的计算机在几个小时后都会耗尽内存。
这是我尝试估计表中的行数时得到的结果:
SELECT reltuples FROM pg_class WHERE relname = 'orders';
reltuples
-------------
4.38543e+08
(1 row)
【问题讨论】:
你能显示你的表 DDL 和你正在执行的删除语句吗?如果您将删除转换为选择计数(*),您的删除目标是多少行? @JustBob select count(1) 花了一个多小时才停止。 我的想法是批量删除。我很好奇您的删除是在 2 行还是 3 亿行之后进行。如果您有一个很好的索引列,它是一个序列,您可以在行集上滑动并从那里删除。您必须编写一个 python 脚本或其他东西来循环从表中删除,其中 id 介于 min 和 max 之间并提交。执行此操作,直到您到达表的末尾,其中 min 和 max 更改为高于上一个的范围,但仍然只在说 50,000 条记录之后。有意义吗? @JustBob 是的,如果归根结底,我将不得不使用光标以编程方式删除重复项。现在试图理解 bma 的建议。我认为您的想法和他的额外专栏可以一起使用以删除重复项。 @nurettin 我的建议 #1 假设您正在删除 100GB 表的很大一部分并且不希望与大量删除(或一系列删除)相关联的膨胀.如果您只有几百万行要删除,那么请分批执行,并在每次运行后运行 VACUUM。 【参考方案1】:立即想到两个解决方案:
1)。使用 WHERE 子句创建一个新表作为 select * from source table 以确定唯一行。添加索引以匹配源表,然后在事务中重命名它们。这是否对您有用取决于几个因素,包括可用磁盘空间量、表是否在持续使用以及是否允许访问中断等。创建新表的好处是可以紧密打包数据和索引,并且由于省略了非唯一行,因此该表将小于原始表。
2)。在列上创建部分唯一索引并添加 WHERE 子句以过滤掉非唯一索引。 例如:
test=# create table t ( col1 int, col2 int, is_unique boolean);
CREATE TABLE
test=# insert into t values (1,2,true), (2,3,true),(2,3,false);
INSERT 0 3
test=# create unique index concurrently t_col1_col2_uidx on t (col1, col2) where is_unique is true;
CREATE INDEX
test=# \d t
Table "public.t"
Column | Type | Modifiers
-----------+---------+-----------
col1 | integer |
col2 | integer |
is_unique | boolean |
Indexes:
"t_col1_col2_uidx" UNIQUE, btree (col1, col2) WHERE is_unique IS TRUE
【讨论】:
以上是关于删除大型 postgresql 数据库表中的重复行的主要内容,如果未能解决你的问题,请参考以下文章
如果插入语句给出重复键异常(在表中找到行 id=1)如何更新 JDBC(Postgresql)中的语句
一种在大型 PostgreSQL 表中处理/合并“后继记录”的方法?