我有一个 SQL 2019 Server,它是一个多租户环境,因此我上面有很多相同的(除了数据之外)客户数据库。
需要在每个数据库中每 30 分钟聚合一些数据,因此有一个 SQL 作业在单独的数据库中运行,并创建一个客户数据库名称表进行循环,然后生成一些动态 SQL 来针对每个数据库运行依次一个。我省略了数据库名称的生成,但这是循环的代码:
DECLARE @StartTime DATETIME,
@EndTime DATETIME,
@EnterpriseId INT,
@Error NVARCHAR(MAX);
SELECT @AutoId = MIN(AutoId) FROM @DBs;
WHILE @AutoId IS NOT NULL
BEGIN
SELECT @DatabaseName = DatabaseName, @EnterpriseId = EnterpriseId, @DatabaseId = DatabaseId FROM @DBs WHERE AutoId = @AutoId
IF @DatabaseId IS NOT NULL
BEGIN
BEGIN TRY
SET @dynSql = 'USE ' + @DatabaseName + ';';
SET @dynSql = @dynSql + 'EXEC Nightly_CustomerRewards_TransactionEntry_Update;';
SET @StartTime = GETDATE();
PRINT @dynSql;
EXEC(@dynSql)
SET @EndTime = GETDATE();
UPDATE dbo.Enterprise SET AggregationsDuration = DATEDIFF(SECOND, @StartTime, @EndTime) WHERE EnterpriseId = @EnterpriseId
END TRY
BEGIN CATCH
SELECT @Error = CONCAT(@DatabaseName,': ', ERROR_MESSAGE(), ' In ' , ERROR_PROCEDURE(), ' at ' , FORMAT(ERROR_LINE(), 'N0'))
PRINT @Error;
END CATCH
END
SELECT @AutoId = MIN(AutoId) FROM @DBs WHERE AutoId > @AutoId
END
作业执行时(周一),大约在 30 秒内完成,并且对服务器的 CPU 没有产生任何重大影响,并且在本周剩余的时间里一直如此。周日凌晨,数据库重新索引运行,此后该作业大约需要 2 分钟才能完成,并且 CPU 出现巨大峰值。
经过多次谷歌搜索,我发现一些提到在 SQL 作业中设置“SET ARITHABORT ON”的内容。我这样做了,嘿,工作很快又回到了 30 秒,而且没有 CPU 压力。
快进到下周日,重新索引再次运行后,同样的事情再次发生 - 作业又恢复缓慢运行,CPU 峰值再次出现。我注释掉了“SET ARITHABORT ON”行,它再次恢复快速运行,没有 CPU 压力。
过去几周都是这样,我必须在每次重新索引后添加/删除 arithabort 语句,具体取决于最后的状态!
有人对造成此问题的原因以及如何解决它有任何建议吗?
谢谢
如果没有有关查询计划的进一步信息,真的很难说,由于某种原因,您拒绝向我们提供这些信息。
但是看起来您的所有
ARITHABORT
语句所做的都是导致重新编译,因为代码已经更改。这反过来似乎又构成了新的统计信息。
您可以通过将以下语句添加到索引作业的末尾来更轻松地完成此操作:
EXEC sp_recompile N'dbo.YourProcName';