【问题标题】:DELETE and NOT IN query performanceDELETE 和 NOT IN 查询性能
【发布时间】:2019-04-16 22:53:01
【问题描述】:

我有以下表结构:

用户

  • UserId(主键)
  • 用户名

一些物品

  • SomeId(FK 到 Users.UserId)
  • SomeItemId(主键)
  • 姓名
  • 其他东西...

一些其他项目

  • SomeId2(FK 到 Users.UserId)
  • SomeOtherItemId(主键)
  • 姓名
  • 其他东西...

我想从 Users 表中删除 SomeItems 和 SomeOtherItems 表中不存在的记录。

我可以这样做:

DELETE from Users
FROM Users u
WHERE u.UserId NOT IN
   (SELECT DISTINCT SomeId FROM SomeItems

    UNION

    SELECT DISTINCT SomeId2 FROM SomeOtherItems)

但是,它非常慢。我假设它对每条记录执行 UNION 查询,不是吗?有什么方法可以提高性能?

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:

对两个结果应用 distinct 然后合并它们(应用第三个 distinct,都需要排序)不是验证存在的最有效方法。怎么样:

DELETE u
  FROM dbo.Users AS u -- always use schema prefix!
  WHERE NOT EXISTS
  (
    SELECT 1 FROM dbo.SomeItems WHERE SomeId = u.UserId
  )
  AND NOT EXISTS
  (
    SELECT 1 FROM dbo.SomeOtherItems WHERE SomeID2 = u.UserId
  );

【讨论】:

  • 。 . .我认为OR 而不是ANDNOT EXISTS
  • @Yogesh OR 将与 EXISTS 一起使用。检查原始查询的逻辑。
  • 哈,我的回答是一样的。来自我的 +1。
  • @AaronBertrand,谢谢。但是,我的查询和您的查询在性能方面是相同的,都需要大约 60-65 秒才能完成我的数据。
  • @Evgeny 我们需要查看执行计划以了解哪些索引是、不是或可以使用。语法不会导致这种速度,但它可能是一个低效的查询计划(或者,如果左连接在 30 秒而不是 60 秒内运行,则它可能是阻塞的,因为这肯定不应该是效率的两倍)。
【解决方案2】:

最简单的解决方法可能就是将 UNION 更改为 UNION ALL

您将通过删除查询计划的流聚合组件来看到此效果。

毕竟你不在乎列表是否重复

【讨论】:

    【解决方案3】:

    我会为两个连接更改 IN,查询越简单,引擎优化就越容易。

    DELETE from U
    FROM Users U
         left join SomeItems S1 on S1.SomeId = U.UserId
         left join SomeOtherItems S2 on S2.SomeID2 = U.UserId
    WHERE S1.SomeId is null and S2.SomeID2 is null
    

    检查 S1.SomeID 是否为 null 意味着 SomeItems 上不存在 U.UserId。 SomeOtherItems 也是如此。

    确保您在 SomeItems 和 SomeOtherItems 上具有 SomeId 和 SomeID2 的索引。

    【讨论】:

    • 使用索引不需要连接。
    • 引擎也可以轻松优化替代语法。
    • @MarcGuillot 谢谢你的回答。您的查询需要 30 秒才能完成,而我的查询需要 65 秒
    • 不,我不是建议你删除你的答案。我只是想澄清一下,使用索引不需要连接,而且这两种语法对于引擎优化来说都不是“更容易”,您的回答表明了这一点。
    • @MarcGuillot 不,我在这些特定列上没有索引,但在其他一些列上有索引(问题中甚至没有提到)。
    猜你喜欢
    • 2016-03-19
    • 2018-10-18
    • 2017-03-30
    • 2020-11-05
    • 2018-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    相关资源
    最近更新 更多