温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何在postgresql中删除重复数据

发布时间:2021-02-05 14:16:01 来源:亿速云 阅读:1089 作者:Leah 栏目:开发技术

这篇文章将为大家详细讲解有关如何在postgresql中删除重复数据,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

首先创建一张基础表,并插入一定量的重复数据。

  test=# create table deltest(id int, name varchar(255));   CREATE TABLE   test=# create table deltest_bk (like deltest);   CREATE TABLE   test=# insert into deltest select generate_series(1, 10000), 'ZhangSan';   INSERT 0 10000   test=# insert into deltest select generate_series(1, 10000), 'ZhangSan';   INSERT 0 10000   test=# insert into deltest_bk select * from deltest;

常规删除方法

最容易想到的方法就是判断数据是否重复,对于重复的数据只保留ctid最小(或最大)的那条数据,删除其他的数据。

test=# explain analyse delete from deltest a where a.ctid <> (select min(t.ctid) from deltest t where a.id=t.id);                                QUERY PLAN   -----------------------------------------------------------------------------------------------------------------------------   Delete on deltest a (cost=0.00..195616.30 rows=1518 width=6) (actual time=67758.866..67758.866 rows=0 loops=1)     -> Seq Scan on deltest a (cost=0.00..195616.30 rows=1518 width=6) (actual time=32896.517..67663.228 rows=10000 loops=1)      Filter: (ctid <> (SubPlan 1))      Rows Removed by Filter: 10000      SubPlan 1       -> Aggregate (cost=128.10..128.10 rows=1 width=6) (actual time=3.374..3.374 rows=1 loops=20000)          -> Seq Scan on deltest t (cost=0.00..128.07 rows=8 width=6) (actual time=0.831..3.344 rows=2 loops=20000)             Filter: (a.id = id)             Rows Removed by Filter: 19998   Total runtime: 67758.931 ms   test=# select count(*) from deltest;   count   -------   10000   (1 行记录)

可以看到,id相同的数据,保留ctid最小的那条,其他的删除。相当于把deltest表中的数据删掉一半,耗时达到67s多。相当慢。

group by删除方法

第二种方法为group by方法,通过分组找到ctid最小的数据,然后删除其他数据。

  test=# truncate table deltest;   TRUNCATE TABLE   test=# insert into deltest select * from deltest_bk;   INSERT 0 20000   test=# explain analyse delete from deltest a where a.ctid not in (select min(ctid) from deltest group by id);                                QUERY PLAN   ----------------------------------------------------------------------------------------------------------------------------------   Delete on deltest a (cost=131.89..2930.46 rows=763 width=6) (actual time=30942.496..30942.496 rows=0 loops=1)     -> Seq Scan on deltest a (cost=131.89..2930.46 rows=763 width=6) (actual time=10186.296..30814.366 rows=10000 loops=1)      Filter: (NOT (SubPlan 1))      Rows Removed by Filter: 10000      SubPlan 1       -> Materialize (cost=131.89..134.89 rows=200 width=10) (actual time=0.001..0.471 rows=7500 loops=20000)          -> HashAggregate (cost=131.89..133.89 rows=200 width=10) (actual time=10.568..13.584 rows=10000 loops=1)             -> Seq Scan on deltest (cost=0.00..124.26 rows=1526 width=10) (actual time=0.006..3.829 rows=20000 loops=1)    Total runtime: 30942.819 ms   (9 行记录)   test=# select count(*) from deltest;    count   -------   10000   (1 行记录)

可以看到同样是删除一半的数据,使用group by的方式,时间节省了一半。但仍含需要30s,下面试一下第三种删除操作。

新的删除方法

在postgres修炼之道这本书中,作者提到一种效率较高的删除方法, 在这里验证一下,具体如下:

  test=# truncate table deltest;   TRUNCATE TABLE   test=# insert into deltest select * from deltest_bk;   INSERT 0 20000                                test=# explain analyze delete from deltest a where a.ctid = any(array (select ctid from (select row_number() over (partition by id), ctid from deltest) t where t.row_number > 1));                                QUERY PLAN   ----------------------------------------------------------------------------------------------------------------------------------   Delete on deltest a (cost=250.74..270.84 rows=10 width=6) (actual time=98.363..98.363 rows=0 loops=1)   InitPlan 1 (returns $0)    -> Subquery Scan on t (cost=204.95..250.73 rows=509 width=6) (actual time=29.446..47.867 rows=10000 loops=1)       Filter: (t.row_number > 1)       Rows Removed by Filter: 10000       -> WindowAgg (cost=204.95..231.66 rows=1526 width=10) (actual time=29.436..44.790 rows=20000 loops=1)          -> Sort (cost=204.95..208.77 rows=1526 width=10) (actual time=12.466..13.754 rows=20000 loops=1)             Sort Key: deltest.id             Sort Method: quicksort Memory: 1294kB             -> Seq Scan on deltest (cost=0.00..124.26 rows=1526 width=10) (actual time=0.021..5.110 rows=20000 loops=1)   -> Tid Scan on deltest a (cost=0.01..20.11 rows=10 width=6) (actual time=82.983..88.751 rows=10000 loops=1)      TID Cond: (ctid = ANY ($0))   Total runtime: 98.912 ms   (13 行记录)   test=# select count(*) from deltest;   count   -------   10000   (1 行记录)

看到上述结果,真让我吃惊了一把,这么快的删除方法还是首次看到,自己真实孤陋寡闻,在这里要膜拜一下修炼之道这本书的大神作者了。

补充:pgsql 删除表中重复数据保留其中的一条

1.在表中(表名:table 主键:id)增加一个字段rownum,类型为serial

2.执行语句:

delete from table where rownum not in(  select max(rownum) from table group by id  )

3.最后删除rownum

关于如何在postgresql中删除重复数据就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI