在NOT IN内部进行转换会使查询运行速度变慢

时间:2015-09-18 09:17:37

标签: sql sql-server sql-server-2008 casting

我必须根据以下条件更新我的TEMP表的记录(用户定义的表类型的变量)。

  1. 我的TEMP表中的ArticleNumber是VARCHAR(100)
  2. 我的文章表中的ArticleNumber是BIGINT
  3. 我希望将所有记录更新为IsValidArticle = 0,当我的TEMP表中的ArticleNumber不在条款表中
  4. 解决方案1:
    转换物理表的ArticleNumber。这需要大约10分钟

    UPDATE @RebalanceRecsSet
            SET [IsValidArticle] = 0 
                ,ProcessedStatus = 'INVALID'
        WHERE Article NOT IN (
                              SELECT CAST(ArticleNumber AS VARCHAR(100)) FROM MDR.dbo.Article
                             )
    

    解决方案2:
    这可以在10秒内完成。但是,我不能这样做。因为它在我的TEMP表中可以有很少的NONINT(BIGINT)值

    UPDATE @RebalanceRecsSet
            SET [IsValidArticle] = 0 
                ,ProcessedStatus = 'INVALID'
        WHERE CAST(Article AS BIGINT) NOT IN 
                             (SELECT ArticleNumber FROM MDR.dbo.Article)
    

    我错过了什么吗?有没有其他方法来实现这一目标?

      

    注意:我的TEMP表的ArticleNumber将为VARCHAR(100)

1 个答案:

答案 0 :(得分:1)

试试这个,它没有昂贵的转换。避免转换错误,除非您的表变量中有一些奇怪的varchars被视为数字。如果表变量中有很多行,则使用临时表可能更有效。

UPDATE  r
SET [IsValidArticle] = 0 
    ,ProcessedStatus = 'INVALID'
FROM @RebalanceRecsSet r
WHERE
  Article NOT IN 
    ( SELECT ArticleNumber 
      FROM MDR.dbo.Article 
      WHERE isnumeric(r.Article) = 1)

编写更新的另一种更有效的方法:

UPDATE  r
SET [IsValidArticle] = 0 
    ,ProcessedStatus = 'INVALID'
FROM
  @RebalanceRecsSet r
LEFT JOIN 
  MDR.dbo.Article
ON
  isnumeric(r.Article) = 1 and
  x.ArticleNumber = r.Article
WHERE x.ArticleNumber is null

值得一提的是,空varchar在比较中将等于0.