我正在尝试从表中删除重复的行,但似乎无效。
查询
DELETE FROM notifications N1
USING notifications N2
WHERE N1.id < N2.id
AND N1.user_id = N2.user_id
AND N1.notification_type = N2.notification_type;
有些SGDB表示与通知表无关。如果我在另一个应用程序中运行它需要1小时才能删除它们,但看起来它最终永远不会提交并返回到之前的状态。 该数据库是一个AWS RDS实例,该表包含超过4000万行,我预计最终不到1英里。
假设:
我不确定我必须遵循什么方法。
答案 0 :(得分:1)
如果没有要测试的完整数据,很难给出明确的答案,但您可能会发现将查询分为两部分会有所帮助:确定要删除的行并删除它们。
CREATE TEMPORARY TABLE temp_notifications_to_delete (
id Int
)
INSERT INTO temp_notifications_to_delete ( id )
SELECT N1.id
FROM notifications N1
JOIN notifications N2
ON N1.id < N2.id
AND N1.user_id = N2.user_id
AND N1.notification_type = N2.notification_type;
DELETE FROM notifications N
USING temp_notifications_to_delete D
WHERE N.id = D.id
以这种方式分隔可以防止在计算要删除的行时锁定表。它还可以更轻松地测试SELECT部分的其他改进,例如添加相关索引,以及使用替代形式的查询。
如a_horse_with_no_name所述,您可以使用EXISTS:
INSERT INTO temp_notifications_to_delete ( id )
SELECT N1.id
FROM notifications N1
WHERE EXISTS (
SELECT *
FROM notifications N2
WHERE N1.id < N2.id
AND N1.user_id = N2.user_id
AND N1.notification_type = N2.notification_type
);
如果您确定为每个user_id,notification_type对一次删除一个副本,则可以使用GROUP BY
:
INSERT INTO temp_notifications_to_delete ( id )
SELECT MIN(id)
FROM notifications
GROUP BY user_id, notification_type
HAVING COUNT(*) > 1;
Panagiotis Kanavos使用窗口函数的建议听起来也很有希望,虽然我不知道他们想到的确切查询。