当我尝试在大型表上创建唯一索引时,我得到一个独特的约束错误。在这种情况下,唯一索引是4列的复合键。
是否有一种有效的方法来识别重复项:
select col1, col2, col3, col4, count(*)
from Table1
group by col1, col2, col3, col4
having count(*) > 1
上面的解释计划显示了具有极高成本的全表扫描,并且只想找到是否有其他方法。
谢谢!
答案 0 :(得分:7)
首先尝试在这四列上创建非唯一索引。这将花费O(n log n)时间,但也会减少执行select
到O(n log n)所需的时间。
你在这里有点绑定 - 无论你怎样切片,整个表必须至少读一次。天真算法在O(n 2 )时间内运行,除非查询优化器足够聪明以构建临时索引/表。
答案 1 :(得分:2)
您可以使用EXCEPTIONS INTO子句来捕获重复的行。
如果您还没有EXCEPTIONS表,请使用提供的脚本创建一个:
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是访问任何给定行的最快方式。
答案 2 :(得分:1)
由于这些列上没有索引,因此该查询必须执行全表扫描 - 除非其中一个或多个列已经编入索引,否则无法正常执行此操作。
您可以将索引创建为非唯一索引,然后运行查询以标识重复行(创建索引后应该非常快)。但是我怀疑创建非唯一索引然后运行查询的总时间是否比仅运行没有索引的查询要少。
答案 3 :(得分:1)
实际上,您需要查找表中每一行的副本。没有索引就无法有效地做到这一点。
答案 4 :(得分:0)
不幸的是,我认为没有更快的方法。