PostgreSQL 中如何delete重复数据

问题提出

时常有这样的case: DB实例运行一段时间后,发现需要给1个table中的某(些)字段加unique 约束,

但创建unique constraints(或 index)时, 报出 DETAIL: Key (col)=(value) is duplicated !

此时就需要先按照一定逻辑将重复数据仅保留1条, 将冗余的delete掉

分析问题

delete数据, 重点自然在于定位所有待delete的row, 或需要保留的row.

解决问题

以假设业务要求要保留如下test表中每组info重复值中id最小的row为例
在这里插入图片描述

方法1 正向思维, 使用 array

使用高级数据类型array及其强大的function, 一次定位需要delete的row
在这里插入图片描述

方法2 正向思维, 使用 window function

思路同 方法1, 让我们体验一下 window function
在这里插入图片描述

方法3 逆向思维, 使用 not in

排除法, 逆向定位
在这里插入图片描述

方法4 逆向思维, 使用 not exists

思路同 方法3
在这里插入图片描述

方法5 正逆结合, 使用 in, not in

先定位存在重复值的组大集合,再排除小集合
在这里插入图片描述

方法6 正逆结合, 使用 exists, not exists

思路同 方法5
在这里插入图片描述

方法7 直接制作单条SQL

将所有存在重复值的组找到, 然后逐一定位需要保留每组中的最小id, 其余delete
在这里插入图片描述

方法8 复制数据到新表

如果应用可以接受短暂停止写入, 可以将所需唯一数据复制到新表
在这里插入图片描述
放在事务里是为了保证所做操作原子性, 避免出现瞬间无表可用的窗口期

注: 为了便于与其他方式对比, 方法8会按照保留id的方式测试, 如果不保留id, group by 比 distinct 执行速度略快.

测试数据

由于query在 table 数据分布不同的情况下执行效率存在差异, 所以我们构造3组测试数据进行对比

生成数据

在这里插入图片描述
数据分布
在这里插入图片描述

各种方法对比

在这里插入图片描述
分析上表可知,

使用正向思维(方法1,2), 平均执行时间会随着冗余数据的增加而增加, 在冗余数据较少时, 推荐方法2;

使用逆向思维(方法3,4), 平均执行时间会随着冗余数据的增加而减少, 在冗余数据较多时, 推荐方法4;

正逆结合的思维(方法5,6)平均执行时间并不占优势, 原因是需要2次subquery来最终定位数据;

方法7 方法7 执行总时间最长(随着单条SQL的总条数的增加而增加),

但实际上对DB实例的冲击最小, 把1个长时间的对大量row 的lock, 离散化为仅对单个row或几个row的极短时间的lock,

在压力较大的生产环境中, 推荐此方法;

方法8 步骤稍繁, 在实际生产环境中由于table的字段可能较多,且整个table的(包括所有index)都会重建, 所以速度并不占优, 但却顺便把table彻底维护了一下 , 对于udpate, delete非常频繁的table, total size(包括所有index)会大为缩小(由于MVCC), 综合性能会明显提升.

总结

看一下DELETE 的语法
在这里插入图片描述
所以其实还有其他一些具体方法, 比如 使用 WITH Queries构造临时表, 使用 USING using_list 替代子查询, 使用存储过程将方法1封装起来(不推荐,因为这样整个delete过程为一个大事务)等等;

但整体思路无外乎上面的套路, 条条大路通罗马,结合table中数据分布情况(具体问题具体分析),选择效率较高, 且是您最钟情的那个style就可以了.

DBA 日常操作选取原则

压力大的线上生产DB实例(尤其是交易系统), 首选对生产冲击最小的,

压力不大的生产DB实例或DB beta/dev 实例首选一条SQL且执行时间快的方法。

重复值delete之后,就可以创建唯一索引了,方法如下:
在这里插入图片描述

参考链接 :

PostgreSQL 中如何delete重复数据 :http://www.yunweipai.com/20062.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值