Mysql DELETE其中ID不存在于多个表中 - 最佳实践?

时间:2016-10-04 17:37:22

标签: mysql

我想删除在活动或照片或电子邮件订阅者中不存在的人。也许他们是,但他们被标记的唯一照片被删除,或他们所处的事件被从数据库中清除。

两个明显的选择:

1)

DELETE FROM people

WHERE personPK NOT IN (
    SELECT personFK FROM attendees
        UNION
    SELECT personFK FROM photo_tags
        UNION
    SELECT personFK FROM email_subscriptions
)

2)

DELETE people FROM people

LEFT JOIN attendees A on A.personFK = personPK
LEFT JOIN photo_tags P on P.personFK = personPK
LEFT JOIN email_subscriptions E on E.personFK = personPK

WHERE attendeePK IS NULL
  AND photoTagPK IS NULL
  AND emailSubPK IS NULL

A& A P大约一百万行,E几千。

第一个选项工作正常,大约需要10秒钟。

第二个选项超时。

是否有更聪明,更好,更快的第三选择?

2 个答案:

答案 0 :(得分:3)

这就是我要做的事情,例如,如上所述的数百万行半虚构架构。

对于这个人,我会添加与子表相关的计数列,每个1和一个日期时间。如

photoCount INT NOT NULL, 
...
lastUpdt DATETIME NOT NULL,

当对子表进行INSERT / UPDATE时(主要焦点自然是插入),我会

  1. 开始交易
  2. 执行"选择更新"在父(people)行
  3. 上呈现Intention Lock
  4. 执行子插入,例如新图片或电子邮件
  5. 增加父相关计数变量并设置lastUpdt=now()
  6. 提交tran(释放意图锁定)
  7. 对子行的删除与上面一样,但是有一个减量。

    这些是否已完成客户端/存储过程/触发器是您的选择。

    让活动看到12每周发布一次(您选择的频率),删除lastUpdt大于1周的people行,并且计数列全部在零。

    我意识到Intention Lock不是一个完全类比,但关于超时和行级锁定以及对速度的需求是相关的。

    考虑到系统的使用频率,真正的好处和潜在的拖拽,一如既往地精心制作您的索引。

    对于任何定期清理事件,请使用调度程序安排它们在低峰值时间运行。

    所有这些都有一些自然的缺点。但是,如果这些摘要数字对其他个人资料页面有用,并且即时获取它们代价太高,那么您将受益匪浅。此外,你肯定会回避我在你提出的两个解决方案中看到的昂贵的电话。

答案 1 :(得分:1)

我尝试使用postgreSQL复制你的场景。但我认为还有其他事情你没告诉我们。

  

A& A P大约一百万行,E几千。

people = 10k记录
我随机选择9500记录并插入email_subscriptions
然后将{95}条记录复制100次attendeesphoto_tags每张表格总计950k

<强> SQL FIDDLE DEMO

首次查询需要5秒左右 第二个需要11毫秒。