【探索】两种查询和删除重复记录的方法及其性能比较
发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这里我来给出两种查询和删除重复记录的方法,一种是使用rowid辅助完成的,另外一种是借助分析函数的力量来完成的。这两种方法的执行效率相对其他方法是高效的。即便如此,这两种方法之间也有着本质上的性能区别
千家信息网最后更新 2026年10月31日【探索】两种查询和删除重复记录的方法及其性能比较这里我来给出两种查询和删除重复记录的方法,一种是使用rowid辅助完成的,另外一种是借助分析函数的力量来完成的。
这两种方法的执行效率相对其他方法是高效的。即便如此,这两种方法之间也有着本质上的性能区别,我将通过实验的方式给大家展示一下这两种方法,并道出其中的本质差别。
1.创建实验用表并初始化几条样本数据
sec@ora10g> create table t (x number, y varchar2(10));
sec@ora10g> insert into t values (1, 'sec');
sec@ora10g> insert into t values (2, 'Andy01');
sec@ora10g> insert into t values (2, 'Andy02');
sec@ora10g> insert into t values (3, 'Anna');
sec@ora10g> insert into t values (4, 'Anna');
sec@ora10g> insert into t values (5, 'John');
sec@ora10g> commit;
sec@secooler> analyze table t compute statistics for table for all indexes for all indexed columns;
Table analyzed.
sec@ora10g> select * from t;
X Y
---------- --------------------
1 sec
2 Andy01
2 Andy02
3 Anna
4 Anna
5 John
6 rows selected.
2.第一种使用rowid辅助查询和删除重复记录的方法
1)查询重复记录
sec@ora10g> SELECT *
2 FROM t t1
3 WHERE t1.ROWID <> (SELECT MIN (t2.ROWID)
4 FROM t t2
5 WHERE t1.x = t2.x)
6 /
X Y
---------- --------------------
2 Andy02
BTW:如果想要查询x和y字段同时重复的内容,可以在上面的子查询中再添加一个"AND t1.y = t2.y"条件即可。
2)删除重复记录
可以简单的将上面的查询语句改写成删除语句便可完成删除任务。
sec@ora10g> DELETE FROM t t1
2 WHERE t1.ROWID <> (SELECT MIN (t2.ROWID)
3 FROM t t2
4 WHERE t1.x = t2.x)
5 /
1 row deleted.
可以看到,此时x字段重复的内容已经被删除了。
sec@ora10g> select * from t;
X Y
---------- --------------------
1 sec
2 Andy01
3 Anna
4 Anna
5 John
3.第二种使用分析函数辅助查询和删除重复记录的方法
1)使用分析函数可以快速的定位重复记录的位置,下面结果中rn值大于1的行即表示重复行。
sec@ora10g> SELECT t1.x,
2 t1.y,
3 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
4 FROM t t1
5 /
X Y RN
---------- -------------------- ----------
1 sec 1
2 Andy01 1
2 Andy02 2
3 Anna 1
4 Anna 1
5 John 1
6 rows selected.
2)进一步使用上面的rn结果作为辅助条件便可得到重复记录内容
sec@ora10g> SELECT t2.x, t2.y
2 FROM (SELECT t1.x,
3 t1.y,
4 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
5 FROM t t1) t2
6 WHERE t2.rn > 1
7 /
X Y
---------- --------------------
2 Andy02
3)删除方法
(1)第一种方法是利用rowid构造delete语句来完成删除,这种方法效率较低。
sec@ora10g> DELETE FROM t WHERE ROWID IN (
2 SELECT rowid
3 FROM (SELECT t1.x,
4 t1.y,
5 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
6 FROM t t1) t2
7 WHERE t2.rn > 1
8 )
9 /
1 row deleted.
(2)第二种方法,可以使用构造中间表t1的方法来完成,这是一种非常高效的去重方法,推荐在具有海量数据的数据库环境中使用。
sec@ora10g> create table t1 as
2 SELECT t2.x, t2.y
3 FROM (SELECT t1.x,
4 t1.y,
5 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
6 FROM t t1) t2
7 WHERE t2.rn = 1
8 /
Table created.
sec@ora10g> drop table t;
Table dropped.
sec@ora10g> alter table t1 rename to t;
Table altered.
sec@ora10g> select * from t;
X Y
---------- --------------------
1 sec
2 Andy01
3 Anna
4 Anna
5 John
4.比较两种查询方法的执行计划,便可得到两种方法内在的性能差距的出处。
1)第一种使用rowid辅助查询的执行计划如下
sec@ora10g> set autot trace exp
sec@ora10g> SELECT *
2 FROM t t1
3 WHERE t1.ROWID <> (SELECT MIN (t2.ROWID)
4 FROM t t2
5 WHERE t1.x = t2.x)
6 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3924487551
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 55 | 6 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL | T | 6 | 66 | 3 (0)| 00:00:01 |
| 3 | SORT AGGREGATE | | 1 | 11 | | |
|* 4 | TABLE ACCESS FULL| T | 1 | 11 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("T1".ROWID<> (SELECT MIN("T2".ROWID) FROM "T" "T2" WHERE
"T2"."X"=:B1))
4 - filter("T2"."X"=:B1)
2)第二种使用分析函数辅助查询的执行计划如下
sec@ora10g> SELECT t1.x,
2 t1.y,
3 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
4 FROM t t1
5 /
Execution Plan
----------------------------------------------------------
Plan hash value: 2335850315
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 66 | 4 (25)| 00:00:01 |
| 1 | WINDOW SORT | | 6 | 66 | 4 (25)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T | 6 | 66 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
3)通过比较上面两个执行计划可以得到如下结论
第一种方法采用2次TABLE ACCESS FULL,第二种方法采用仅一次TABLE ACCESS FULL。
从执行计划上可以得出使用分析函数的方法更加的高效。
5.小结
在DBA数据库维护工作中,重复记录去除问题往往是不可避免的。在具有海量数据的数据库中去除重复记录是一件很艰巨的任务,如果方法选择不正确,很可能难以完成任务。
我这里介绍的两种方法都是相对比较高效的,细节之处请慢慢体会。
完成任务的手段和方法很多,只有将维护时间和对生产数据库的冲击较少到最低的方法才是可以接受的正确方法。
Good luck.
-- The End --
这两种方法的执行效率相对其他方法是高效的。即便如此,这两种方法之间也有着本质上的性能区别,我将通过实验的方式给大家展示一下这两种方法,并道出其中的本质差别。
1.创建实验用表并初始化几条样本数据
sec@ora10g> create table t (x number, y varchar2(10));
sec@ora10g> insert into t values (1, 'sec');
sec@ora10g> insert into t values (2, 'Andy01');
sec@ora10g> insert into t values (2, 'Andy02');
sec@ora10g> insert into t values (3, 'Anna');
sec@ora10g> insert into t values (4, 'Anna');
sec@ora10g> insert into t values (5, 'John');
sec@ora10g> commit;
sec@secooler> analyze table t compute statistics for table for all indexes for all indexed columns;
Table analyzed.
sec@ora10g> select * from t;
X Y
---------- --------------------
1 sec
2 Andy01
2 Andy02
3 Anna
4 Anna
5 John
6 rows selected.
2.第一种使用rowid辅助查询和删除重复记录的方法
1)查询重复记录
sec@ora10g> SELECT *
2 FROM t t1
3 WHERE t1.ROWID <> (SELECT MIN (t2.ROWID)
4 FROM t t2
5 WHERE t1.x = t2.x)
6 /
X Y
---------- --------------------
2 Andy02
BTW:如果想要查询x和y字段同时重复的内容,可以在上面的子查询中再添加一个"AND t1.y = t2.y"条件即可。
2)删除重复记录
可以简单的将上面的查询语句改写成删除语句便可完成删除任务。
sec@ora10g> DELETE FROM t t1
2 WHERE t1.ROWID <> (SELECT MIN (t2.ROWID)
3 FROM t t2
4 WHERE t1.x = t2.x)
5 /
1 row deleted.
可以看到,此时x字段重复的内容已经被删除了。
sec@ora10g> select * from t;
X Y
---------- --------------------
1 sec
2 Andy01
3 Anna
4 Anna
5 John
3.第二种使用分析函数辅助查询和删除重复记录的方法
1)使用分析函数可以快速的定位重复记录的位置,下面结果中rn值大于1的行即表示重复行。
sec@ora10g> SELECT t1.x,
2 t1.y,
3 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
4 FROM t t1
5 /
X Y RN
---------- -------------------- ----------
1 sec 1
2 Andy01 1
2 Andy02 2
3 Anna 1
4 Anna 1
5 John 1
6 rows selected.
2)进一步使用上面的rn结果作为辅助条件便可得到重复记录内容
sec@ora10g> SELECT t2.x, t2.y
2 FROM (SELECT t1.x,
3 t1.y,
4 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
5 FROM t t1) t2
6 WHERE t2.rn > 1
7 /
X Y
---------- --------------------
2 Andy02
3)删除方法
(1)第一种方法是利用rowid构造delete语句来完成删除,这种方法效率较低。
sec@ora10g> DELETE FROM t WHERE ROWID IN (
2 SELECT rowid
3 FROM (SELECT t1.x,
4 t1.y,
5 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
6 FROM t t1) t2
7 WHERE t2.rn > 1
8 )
9 /
1 row deleted.
(2)第二种方法,可以使用构造中间表t1的方法来完成,这是一种非常高效的去重方法,推荐在具有海量数据的数据库环境中使用。
sec@ora10g> create table t1 as
2 SELECT t2.x, t2.y
3 FROM (SELECT t1.x,
4 t1.y,
5 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
6 FROM t t1) t2
7 WHERE t2.rn = 1
8 /
Table created.
sec@ora10g> drop table t;
Table dropped.
sec@ora10g> alter table t1 rename to t;
Table altered.
sec@ora10g> select * from t;
X Y
---------- --------------------
1 sec
2 Andy01
3 Anna
4 Anna
5 John
4.比较两种查询方法的执行计划,便可得到两种方法内在的性能差距的出处。
1)第一种使用rowid辅助查询的执行计划如下
sec@ora10g> set autot trace exp
sec@ora10g> SELECT *
2 FROM t t1
3 WHERE t1.ROWID <> (SELECT MIN (t2.ROWID)
4 FROM t t2
5 WHERE t1.x = t2.x)
6 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3924487551
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 55 | 6 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL | T | 6 | 66 | 3 (0)| 00:00:01 |
| 3 | SORT AGGREGATE | | 1 | 11 | | |
|* 4 | TABLE ACCESS FULL| T | 1 | 11 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("T1".ROWID<> (SELECT MIN("T2".ROWID) FROM "T" "T2" WHERE
"T2"."X"=:B1))
4 - filter("T2"."X"=:B1)
2)第二种使用分析函数辅助查询的执行计划如下
sec@ora10g> SELECT t1.x,
2 t1.y,
3 ROW_NUMBER () OVER (PARTITION BY t1.x ORDER BY t1.ROWID) rn
4 FROM t t1
5 /
Execution Plan
----------------------------------------------------------
Plan hash value: 2335850315
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 66 | 4 (25)| 00:00:01 |
| 1 | WINDOW SORT | | 6 | 66 | 4 (25)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T | 6 | 66 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
3)通过比较上面两个执行计划可以得到如下结论
第一种方法采用2次TABLE ACCESS FULL,第二种方法采用仅一次TABLE ACCESS FULL。
从执行计划上可以得出使用分析函数的方法更加的高效。
5.小结
在DBA数据库维护工作中,重复记录去除问题往往是不可避免的。在具有海量数据的数据库中去除重复记录是一件很艰巨的任务,如果方法选择不正确,很可能难以完成任务。
我这里介绍的两种方法都是相对比较高效的,细节之处请慢慢体会。
完成任务的手段和方法很多,只有将维护时间和对生产数据库的冲击较少到最低的方法才是可以接受的正确方法。
Good luck.
-- The End --
方法
查询
数据
辅助
函数
分析
任务
数据库
内容
语句
面的
性能
字段
效率
本质
条件
海量
结果
实验
最低
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网科技产业
A股互联网金融科技公司
厦门中拓互联网络科技有限公司
互联网 科技
深圳互联网科技公司
易互联网科技有限公司
万易互联网科技有限公司
智慧科技互联网
丰台科技园 互联网
伴你行互联网科技有限公司
上海卓越科技 互联网
互联网科技公司介绍
互联网科技有限公司 翻译
互联网科技创新企业排名
山东吉时兔互联网科技有限公司
互联网汽车科技小镇
互联网科技年终奖
西安左小互联网科技有限公司
福仕德教育科技互联网
第三届互联网大会安防黑科技
百单网互联网科技有限公司
博彦科技互联网金融
广州为想互联网科技有限公司
新华互联网科技
互联网金融监管科技数据
美国互联网科技
易通互联网络科技有限公司
常德市电业局互联网科技部
三亚科技创新互联网基地
优雇互联网科技有限公司