我在SQL Server 2008中编写的查询非常糟糕
UPDATE PatientChartImages
SET PatientChartImages.IsLockDown = @IsLockdown
WHERE PatientChartImages.IsLockDown = @IsNotLockdown
AND PatientChartId IN (
SELECT PatientCharts.PatientChartId
FROM PatientCharts
WHERE ( PatientCharts.ChartStatusID = @ChartCompletedStatusID
OR PatientCharts.ChartStatusID = @ChartOnBaseStatusID
)
AND PatientCharts.IsLockDown = @IsNotLockdown
AND PatientCharts.CompletedOn IS NOT NULL
AND DATEDIFF(MINUTE, PatientCharts.CompletedOn, GETUTCDATE()) >= ( SELECT
tf.LockUpInterval
FROM
@tblFacCOnf tf
WHERE
tf.facilityId = PatientCharts.FacilityId
) )
此查询锁定主表并导致TimeOut。如果我首先在所有可更新记录中创建CTE,然后通过加入CTE来更新主表。它有帮助??
答案 0 :(得分:0)
我建议您做的第一件事是用IN
替换EXISTS
条件。其次是将所有这些条件逻辑移入CTE。第三是用@tblFacCOnf
替换带有连接的子选择。
最后的建议取决于您的业务逻辑,在我看来并不那么重要
所以最后你会得到一些东西
WITH search_cte as (
SELECT PatientCharts.PatientChartId
FROM PatientCharts
JOIN @tblFacCOnf tf on tf.facilityId = PatientCharts.FacilityId
WHERE ( PatientCharts.ChartStatusID = @ChartCompletedStatusID
OR PatientCharts.ChartStatusID = @ChartOnBaseStatusID
)
AND PatientCharts.IsLockDown = @IsNotLockdown
AND PatientCharts.CompletedOn IS NOT NULL
AND DATEDIFF(MINUTE, PatientCharts.CompletedOn, GETUTCDATE()) >= tf.LockUpInterval
) --cte end
UPDATE PatientChartImages
SET PatientChartImages.IsLockDown = @IsLockdown
WHERE PatientChartImages.IsLockDown = @IsNotLockdown
AND EXISTS (select 1 from PatientChartImages where PatientChartImages.PatientChartId = search_cte.PatientChartId)
答案 1 :(得分:0)
如果其他建议没有给你足够的速度,我可能会建议另外一件事就是不要使用表变量。临时表对于大型数据集通常更快,并且如果需要可以编制索引。
答案 2 :(得分:0)
更新锁定的时间是计算CTE和更新时间。 CTE时间可能导致超时。
将锁定时间减少到更新目标表所需的最小值。我建议你创建一个包含两列的临时表。 Col1是目标表的主键或簇键,Col2是目标表中所需的值。包装创建临时表,并根据事务中的业务逻辑为表填充值。使用临时表的连接更新目标表,并在单独的事务中使用临时表中的值更新目标表。更新后删除临时表。
答案 3 :(得分:-1)
我认为您应该创建一个SQL脚本(或存储过程,如果您将从更高级别使用它),您将选择的结果存储到游标中(您只需找到行的PatientCartId)要更新)然后你应该在更新中使用它,所以答案是肯定的。
这很容易测试,您应该将这些命令放入事务中,回滚事务,在回滚之前,您应该执行选择以测试结果。祝你好运。