create table aaa(id bigserial,col1 varchar(255));
insert into aaa values(1,"b"),(2,"a"),(3,"b"),(4,"c");
select * from aaa;
方法1:ctid表示数据行在它所处的表内的物理位置,ctid由两个数字组成,第一个数字表示物理块号,第二个数字表示在物理块中的行号。
select * from aaa where ctid not in(select max(ctid) from aaa group by col1);
删除重复行
(资料图片)
delete from aaa where ctid not in(select max(ctid) from aaa group by col1);
方法2:利用exists
找到重复行
select * from aaa t1 where exists (select 1 from aaa t2 where t1.col1=t2.col1 and t1.id删除重复行
delete from aaa t1 where exists (select 1 from aaa t2 where t1.col1=t2.col1 and t1.idpostgresql常用的删除重复数据方法
最高效方法
测试环境验证,6600万行大表,删除2200万重复数据仅需3分钟
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));PG中三种删除重复数据方法
首先创建一张基础表,并插入一定量的重复数据。
create table deltest(id int, name varchar(255)); create table deltest_bk (like deltest); insert into deltest select generate_series(1, 10000), "ZhangSan"; insert into deltest select generate_series(1, 10000), "ZhangSan"; insert into deltest_bk select * from deltest;1. 常规删除方法
最容易想到的方法就是判断数据是否重复,对于重复的数据只保留ctid最小(或最大)的数据,删除其他的。
explain analyse delete from deltest a where a.ctid <> (select min(t.ctid) from deltest t where a.id=t.id); ------------------------------------------------------------------------------------------- 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 select count(*) from deltest; count ------- 10000可以看到,id相同的数据,保留ctid最小的,其他的删除。相当于把deltest表中的数据删掉一半,耗时达到67s多。相当慢。
2. group by删除方法
group by方法通过分组找到ctid最小的数据,然后删除其他数据。
explain analyse delete from deltest a where a.ctid not in (select min(ctid) from deltest group by id); ------------------------------------------------------------------------------------------- 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 select count(*) from deltest; count ------- 10000可以看到同样是删除一半的数据,使用group by的方式,时间节省了一半。但仍含需要30s,下面试一下第三种删除操作。
3. 高效删除方法
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)); ----------------------------------------------------------------------------------------- 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)−>SubqueryScanont(cost=204.95..250.73rows=509width=6)(actualtime=29.446..47.867rows=10000loops=1)Filter:(t.rownumber>1)RowsRemovedbyFilter:10000−>WindowAgg(cost=204.95..231.66rows=1526width=10)(actualtime=29.436..44.790rows=20000loops=1)−>Sort(cost=204.95..208.77rows=1526width=10)(actualtime=12.466..13.754rows=20000loops=1)SortKey:deltest.idSortMethod:quicksortMemory:1294kB−>SeqScanondeltest(cost=0.00..124.26rows=1526width=10)(actualtime=0.021..5.110rows=20000loops=1)−>TidScanondeltesta(cost=0.01..20.11rows=10width=6)(actualtime=82.983..88.751rows=10000loops=1)TIDCond:(ctid=ANY(0)−>SubqueryScanont(cost=204.95..250.73rows=509width=6)(actualtime=29.446..47.867rows=10000loops=1)Filter:(t.rownumber>1)RowsRemovedbyFilter:10000−>WindowAgg(cost=204.95..231.66rows=1526width=10)(actualtime=29.436..44.790rows=20000loops=1)−>Sort(cost=204.95..208.77rows=1526width=10)(actualtime=12.466..13.754rows=20000loops=1)SortKey:deltest.idSortMethod:quicksortMemory:1294kB−>SeqScanondeltest(cost=0.00..124.26rows=1526width=10)(actualtime=0.021..5.110rows=20000loops=1)−>TidScanondeltesta(cost=0.01..20.11rows=10width=6)(actualtime=82.983..88.751rows=10000loops=1)TIDCond:(ctid=ANY(0)) Total runtime: 98.912 ms select count(*) from deltest; count ------- 10000可以看到,居然只要98ms
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
标签:
这篇文章主要介绍了postgresql如何找到表中重复数据的行并删除问题,具有很好的参考价值,希望对大家有所帮
上实发展表示,公司近期日常经营情况正常,公司、公司控股股东及实际控制人不存在涉及本公司应披露而未披露
5月5日,信澳价值精选混合A最新单位净值为0 8839元,累计净值为0 8839元,较前一交易日下跌0 33%。历史数据
1、你好宇之龙库房货架悬臂货架,横梁货架,周至集贤产业园工厂,轻型仓库货架、重型仓库货架、及塑料托盘
1、采纳。2、TimeZ-偶像万万岁 追求完美的偶像万万岁才华洋溢的偶像万万岁十八般武艺每一样都
直播吧5月5日讯据记者裴力报道,阿根廷队6月份在中国进行的热身赛,对手大概率会是亚洲前六名的某支国家队
5月5日,广州队官方微博发布消息,球队已经与主帅郭士强完成续约。官方原文如下:近日,龙狮篮球俱乐部与郭
【本文由“观察者网用户_518551”推荐,来自《报告称68 5%青年可付房款首付,74 7%倾向购新房,如何看待这一数
1、曹妃甸区唐海镇安子村残协志愿服务小队是由唐山市曹妃甸区残疾人联合会志愿服务队领导下的志愿团体。2、
英雄传说闪之轨迹3有哪些角色?很多玩家对新作的角色非常好奇,下面就为大家整理了英雄传说闪之轨迹3全角色
日前,奇瑞旗下艾瑞泽8 2 0T运动版官图曝光,新车换装了全新进气格栅,整体造型更显运动感,车身细节装饰件
邮储银行吉安市分行开展“让美好发生”主题传播活动,信用卡,邮储银行,传播活动,让美好发生,银行吉安市分行
全省消费品市场累积实现消费额约64 5亿元、重点餐饮企业营业额同比增95 6%、高速日均出口流量433 31万辆、
顺发恒业:关于减持已回购股份的进展公告
今(5)日,上游新闻从风正巴渝获悉,涪陵、秀山两名干部被查处。重庆涪陵能源实业集团有限公司原副总经理
苏丹首都喀土穆4日再次爆发武装冲突,冲突双方苏丹武装部队和快速支援部队分别表示遭到袭击。 新华社报
一分一段表作为统计表格,为决策部门提供支持,方便统筹规划。以高考成绩分段表为例,相关部门通过相应的高
1、是手机游戏,万华镜是一款剧情类型的角色扮演游戏。经典的日系恋爱游戏系列作品,每一作的剧情设计都是
童年的发现上课笔记划重点
大陆无人机绕台引关注,岛内媒体人:反观台“中科院”,不知何时启用,军舰,大陆,无人机,反潜机,解放军,...
X 关闭
X 关闭