用于删除的 IF 语句的替代方法

问题描述

我在 SSIS 执行 sql 任务中运行了以下脚本,该任务需要很长时间才能执行:

DECLARE @Year int
DECLARE @Month int

SET @Year = YEAR(GETDATE())
SET @Month = MONTH(GETDATE())

IF @Month IN (1,2,3,4,5,6,7,8,9)
 BEGIN

  SET @Year = @Year-1

  DELETE FROM GLYTDMovement 
  WHERE CGYear >= @Year
   AND Entity NOT LIKE 'TT%'

 END
ELSE
 BEGIN

  SET @Year = @Year

  DELETE FROM GLYTDMovement 
  WHERE CGYear >= @Year
   AND Entity NOT LIKE 'TT%'

 END

关于如何调整以提高性能的任何建议?

解决方法

您可能想尝试以下操作:

DECLARE @Year int
DECLARE @Month int

SET @Year = YEAR(GETDATE())
SET @Month = MONTH(GETDATE())

DELETE FROM GLYTDMovement 
WHERE Entity NOT LIKE 'TT%'
  AND ((CGYear >= @Year-1 AND @Month <= 9) OR (CGYear >= @Year AND @Month >= 10))

此外,可能值得尝试评估此语句之外的当前日期年和月,然后在删除中使用表达式,如下所示:

...AND ((CGYear >= 2021-1 AND 3 <= 9) OR (CGYear >= 2021 AND 3 >= 10))

SQL Server / SSIS 在处理 WHERE 条件中的变量时往往性能较低。

,

您的代码只执行一个 DELETE 语句。您几乎无法加快速度——没有循环、连接或任何其他想到的东西。

可能的问题是什么?

  • 表可能非常非常大,WHERE 子句需要全表扫描。
  • 可能会删除很多行。
  • 资源争用和锁定。

对于后两个,您无能为力。第一个比较棘手,但您可能会发现 (Entity,CGYear) 上的简单索引可以加快查询速度。

对于更集中的索引,您可以创建过滤索引:

create index fidx_GLYTDMovement_year on GLYTDMovement(year)
    where Entity >= 'TT' and Entity < 'TU';

这等价于您的逻辑(假设合理的排序规则),但过滤索引不支持 LIKE

然后确保在查询中使用相同的 WHERE 子句:

WHERE CGYear >= @Year AND
      Entity >= 'TT' and Entity < 'TU'