postgresql 常用的删除重复数据方法
一、 最高效方法
测试环境验证,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
postgresql 常用的删除重复数据方法的更多相关文章
- orcl数据库查询重复数据及删除重复数据方法
工作中,发现数据库表中有许多重复的数据,而这个时候老板需要统计表中有多少条数据时(不包含重复数据),只想说一句MMP,库中好几十万数据,肿么办,无奈只能自己在网上找语句,最终成功解救,下面是我一个实验 ...
- 【转】SQL删除重复数据方法,留着备用
感谢孙潇楠前辈的总结,地址http://www.cnblogs.com/sunxiaonan/archive/2009/11/24/1609439.html 例如: id name ...
- (转载)SQL删除重复数据方法
本文转载自http://www.cnblogs.com/sunxiaonan/archive/2009/11/24/1609439.html 例如: id name ...
- 教你几种在SQLServer中删除重复数据方法(转)
转载地址:http://www.jb51.net/article/22980.htm 方法一 复制代码 代码如下: declare @max integer,@id integer declare c ...
- SQL删除重复数据方法
例如: id name value 1 a pp 2 a ...
- 【转】SQL删除重复数据方法
例如: id name value 1 a pp 2 a ...
- mysql删除重复数据方法
create table tmp SELECT * from lhb t where t.id not in (select max(id) from lhb group by code,date,r ...
- oracle 快速删除大批量数据方法(全部删除,条件删除,删除大量重复记录)
oracle 快速删除大批量数据方法(全部删除,条件删除,删除大量重复记录) 分类: ORACLE 数据库 2011-05-24 16:39 8427人阅读 评论(2) 收藏 举报 oracledel ...
- MySQL中删除重复数据的简单方法,mysql删除重复数据
MYSQL里有五百万数据,但大多是重复的,真实的就180万,于是想怎样把这些重复的数据搞出来,在网上找了一圈,好多是用NOT IN这样的代码,这样效率很低,自己琢磨组合了一下,找到一个高效的处理方式, ...
- MSSQL如何在没有主键的表中删除重复数据
为了对重复数据进行实验,下面建一个设计不太好(没有主键)表并插入了一些重复数据: create database testdb use testdb ; go create table DupsNoP ...
随机推荐
- jjava基础语法
java基础语法1 注释 注意: SDK要选择JDK1.8,且下面的语言要选择8,配置完这个环境后,JAVA才能正常运行. 单行注释 //+text 快捷键:ctrl+/ 多行注释 /*+text+ ...
- SQL注入问题、视图、触发器、事物、存储过程、函数、流程控制、索引相关概念、索引数据结构、慢查询优化、
目录 SQL注入问题 视图 触发器 事物 存储过程 函数 流程控制 索引相关概念 索引数据结构 慢查询优化 测试装备 联合索引 全文检索 插入数据 更新数据 删除数据 主键 外键 重命名表 事物 安全 ...
- Windows11家庭中文版——启用或关闭Windows功能中找不到hyper解决方法
Windows11家庭中文版找不到hyper解决方法: 1.将如下代码添加到记事本中,并另存为[Hyper-V.bat]文件,代码如下: pushd "%~dp0" dir /b ...
- SQLMap入门——获取数据库用户的密码
列出数据库用户的密码 如果当前用户有读取包含用户密码的权限,SQLMap会先列举出用户,然后列出Hash,并尝试破解 python sqlmap.py -u http://localhost/sqli ...
- JavaScript:显式转换数据类型:如何转换为数值、字符串和布尔值类型?
JS的运算符以及某些内置函数,会自动进行数据类型的转换,方便计算,即隐式转换数据类型: 但是很多时候,我们希望可以手动控制数据类型的转换,即显示转换数据类型: 转换为字符串 String()函数 使用 ...
- JavaScript:七大基础数据类型:字符串string
在JS中,字符串类型的数据,有三种表达方式,但是无一例外都是需要引号扩起来的: 单引号'hello' 双引号"hello" 反引号`hello` 注意: 因为JS没有字符类型,这一 ...
- Netty-架构设计及入门程序-3
一.原生 NIO 存在的问题 1.NIO 的类库和 API 繁杂,使用麻烦:需要熟练掌握 Selector.ServerSocketChannel.SocketChannel.ByteBuffer等. ...
- MySQL 索引的创建、删除
MySQL中索引的创建有三种方法,索引的删除有两种方法. 一.创建索引 (1)使用create index # 1.创建普通索引 create index 索引名 on 表名 (列名[(限制索引长度) ...
- Python基本数据类型,用户交互,格式化输出,运算符,多种赋值方式,多种运算符
Python基本数据类型,用户交互,格式化输出,运算符,多种赋值方式,多种运算符 一.Python基本数据类型 1.回顾之前学过的基本数据类型 1.整型(整数) 应用场景:年级,班级人数,年份 代码实 ...
- 前端基础知识-react(一)个人学习记录 _
待补充 reactive和ref