Oracle:在没有索引的表中识别重复项

Oracle:在没有索引的表中识别重复项,oracle,plsql,duplicates,Oracle,Plsql,Duplicates,当我试图在一个大表上创建一个唯一的索引时,我得到一个唯一的约束错误。本例中的唯一索引是由4列组成的复合键 是否有一种有效的方法来识别重复项,而不是: select col1, col2, col3, col4, count(*) from Table1 group by col1, col2, col3, col4 having count(*) > 1 上面的解释计划显示了成本极高的全表扫描,只是想知道是否还有其他方法 谢谢 由于这些列上没有索引,因此该查询必须执行完整的表扫描—实际上

当我试图在一个大表上创建一个唯一的索引时,我得到一个唯一的约束错误。本例中的唯一索引是由4列组成的复合键

是否有一种有效的方法来识别重复项,而不是:

select col1, col2, col3, col4, count(*)
from Table1
group by col1, col2, col3, col4
having count(*) > 1
上面的解释计划显示了成本极高的全表扫描,只是想知道是否还有其他方法


谢谢

由于这些列上没有索引,因此该查询必须执行完整的表扫描—实际上没有其他方法可以这样做,除非其中一个或多个列已经被索引


您可以将索引创建为非唯一索引,然后运行查询以识别重复的行(创建索引后应该非常快)。但是我怀疑创建非唯一索引然后运行查询的总时间是否会比不使用索引运行查询的总时间少。

不幸的是,我认为没有更快的方法。

首先尝试在这四列上创建非唯一索引。这将需要O(n log n)时间,但也将减少执行
选择
到O(n log n)所需的时间


您在这里遇到了一点麻烦--无论您以何种方式对其进行切片,整个表都必须至少读入一次。除非查询优化器足够聪明,能够构建一个临时索引/表,否则这种天真的算法将在O(n2)时间内运行。

事实上,您需要查找表中每一行的副本。如果没有索引,就无法有效地执行此操作。

您可以使用EXCEPTIONS INTO子句来捕获重复的行

如果您还没有异常表,请使用提供的脚本创建一个异常表:

SQL>  @$ORACLE_HOME/rdbms/admin/ultexcpt.sql
现在您可以尝试创建这样的唯一约束

alter table Table1
add  constraint tab1_uq UNIQUE (col1, col2, col3, col4)
exceptions into exceptions
/
这将失败,但现在您的EXCEPTIONS表包含一个由ROWID标识的所有行的列表,这些行的键包含重复项。这为您决定如何处理重复项(删除、重新编号等)提供了基础

编辑


正如其他人所指出的,您必须支付扫描表一次的费用。这种方法为您提供了一组永久的重复行,ROWID是访问任何给定行的最快方法。

解决非唯一问题后,您可以使用创建的非唯一索引强制执行唯一约束。当您在同一列上有一个非唯一索引时,它不允许您创建唯一索引,因此如果您确实想要一个唯一索引,请在表1(col1、col2、col3、col4,1)上创建非唯一索引作为create index t_ix;如果文本位于末尾,它不会阻止您稍后在col1、col2、col3、col4上创建唯一索引,然后删除非唯一索引。所有回复都表明没有简单的方法可以解决此问题。但是这个答案也给了我一个方法,所以我选择这个作为我问题的最佳答案。谢谢你,杰夫。