【问题标题】:SQL - improve NOT EXISTS query performanceSQL - 提高 NOT EXISTS 查询性能
【发布时间】:2010-10-07 23:00:04
【问题描述】:

有没有办法可以提高这种SQL查询的性能:

INSERT
INTO ...
WHERE NOT EXISTS(Validation...)

问题是当我的表中有很多数据(如数百万行)时,WHERE NOT EXISTS 子句的执行速度很慢。我必须进行此验证,因为我无法插入重复的数据。

我使用 SQLServer 2005

谢谢

【问题讨论】:

  • 你是从一个表插入到另一个表吗?
  • 是的,但它们的格式不同。例如,在表 A 中,日期是整数 20070102,在表 B 中,表是日期时间
  • 通常如果你可以不存在,那么可能有一种方法可以切换到使用 EXISTS ...可能需要一个额外的临时表,但它可能会更快

标签: sql sql-server performance where-clause not-exists


【解决方案1】:

确保您在索引列上进行搜索,并且不对这些列中的数据进行任何操作(如子字符串等)

【讨论】:

    【解决方案2】:

    在我的脑海中,您可以尝试以下方法:

     TRUNCATE temptable
     INSERT INTO temptable ...
     INSERT INTO temptable ... 
     ...
     INSERT INTO realtable
     SELECT temptable.* FROM temptable
     LEFT JOIN realtable on realtable.key = temptable.key
     WHERE realtable.key is null
    

    【讨论】:

    • 在我对数百万行表的测试中,这是迄今为止最快的解决方案... OP 的选项持续几分钟,接受的(ck 的)答案持续几分钟,您的解决方案持续 10 秒(我在所有解决方案中都使用了正确的索引)
    【解决方案3】:

    尝试将 NOT EXISTS 替换为左外连接,它有时在大型数据集中表现更好。

    【讨论】:

    • 有趣的是,我经常发现相反的情况。 EXISTS 将在找到的第一个匹配项处停止搜索,而连接会生成所有可能的匹配项。因此 EXISTS 应该更快。我想。
    • 问题是,NOT EXISTS 总是会导致表扫描,而如果你小心你的连接,你可能只使用索引。
    • ávio,我不认为 N​​OT EXISTS 总是会导致表扫描。看到这个帖子:social.msdn.microsoft.com/Forums/en-US/transactsql/thread/…
    【解决方案4】:

    注意关于索引的其他答案。如果您有良好的索引,NOT EXISTS 通常会很快。

    但我对您描述的陈述有性能问题。我用来解决这个问题的一种方法是使用临时表作为候选值,执行 DELETE FROM ... WHERE EXISTS (...),然后盲目地插入剩余部分。在事务内部,当然要避免竞争条件。拆分查询有时可以让优化器完成其工作而不会感到困惑。

    【讨论】:

      【解决方案5】:

      外部应用往往对我有用...

      代替:

      from t1
      where not exists (select 1 from t2 where t1.something=t2.something)
      

      我会用:

      from t1
      outer apply (
          select top 1 1 as found from t2 where t1.something=t2.something
      ) t2f
      where t2f.found is null
      

      【讨论】:

        【解决方案6】:

        如果您完全可以减少问题空间,那么您将获得大量性能。您确定该表中的每一行都需要检查吗?

        您可能想尝试的另一件事是在插入之前添加DELETE InsertTable FROM InsertTable INNER JOIN ExistingTable ON <Validation criteria>。但是,您的里程可能会有所不同

        【讨论】:

          【解决方案7】:
          insert into customers 
          select * 
          from newcustomers 
          where customerid not in (select customerid 
                                   from customers)
          

          ..可能更有效。正如其他人所说,确保您在任何查找字段上都有索引。

          【讨论】:

            猜你喜欢
            • 2014-04-25
            • 1970-01-01
            • 1970-01-01
            • 2016-07-22
            • 1970-01-01
            • 2017-05-26
            • 2016-09-19
            • 1970-01-01
            相关资源
            最近更新 更多