我一直使用这种查询删除重复项:
delete from test a
using test b
where a.ctid < b.ctid
and a.col1=b.col1
and a.col2=b.col2
and a.col3=b.col3
此外,我已经看到此查询正在使用:
DELETE FROM test WHERE test.ctid NOT IN
(SELECT ctid FROM (
SELECT DISTINCT ON (col1, col2) *
FROM test));
甚至是这个(重复操作,直到重复用完为止):
delete from test ju where ju.ctid in
(select ctid from (
select distinct on (col1, col2) * from test ou
where (select count(*) from test inr
where inr.col1= ou.col1 and inr.col2=ou.col2) > 1
现在,我遇到了一个具有500万行的表,其中的行索引将与where子句匹配。现在我不知道:
在所有这些方法中,哪些似乎最有效?为什么最有效?为什么? 我只运行第二个,要花45分钟以上的时间才能删除重复项。我只是好奇哪个会是最高效的,以防万一我不得不从另一个巨大的表中删除重复项。首先它具有主键并不重要,您始终可以创建它。
答案 0 :(得分:2)
使用row_number()
window function可以很容易地找到重复项:
SELECT ctid
FROM(
SELECT
*,
ctid,
row_number() OVER (PARTITION BY col1, col2, col3 ORDER BY ctid)
FROM test
)s
WHERE row_number >= 2
此命令对组绑定的行进行排序,并添加一个行计数器。因此,带有row_number > 1
的每一行都是重复项,可以删除:
DELETE
FROM test
WHERE ctid IN
(
SELECT ctid
FROM(
SELECT
*,
ctid,
row_number() OVER (PARTITION BY col1, col2, col3 ORDER BY ctid)
FROM test
)s
WHERE row_number >= 2
)
我不知道此解决方案是否比您尝试的快,但是您可以尝试一下。
此外-正如已经提到的@a_horse_with_no_name-对于性能问题,我建议使用自己的标识符而不是ctid
。
修改:
对于我的测试数据,您的第一个版本似乎比我的解决方案要快一点。您的第二个版本似乎较慢,而您的第三个版本对我不起作用(修复了编译错误后,它没有显示结果)。