在这种情况下创建 CTE 有帮助吗?
我有一个在 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
) )
该查询锁定主表并导致超时。如果我首先创建 CTE 所有可更新记录,然后通过加入 CTE 来更新主表。有帮助吗??
I have a query written very poorly in 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
) )
This query locks the main table and results in TimeOut. IF i create a CTE first of all the updateable records and then update the main table by joining to the CTE. Will it help ??
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我建议您做的第一件事就是用
EXISTS
替换IN
条件。其次是将所有这些条件逻辑转移到 CTE 中。第三种方法是将子选择替换为@tblFacCOnf
和 join。最后的建议取决于您的业务逻辑,在我看来并不那么重要
所以最后您会得到如下内容
First thing i advice you to do is to substitute
IN
condition withEXISTS
. Second is to move all this conditional logic into CTE. Third is to substitute sub-select with@tblFacCOnf
with join.Last advice depends on your business logic and is not so important in my opinion
So at the end you will get something as
如果其他建议不能让您获得足够的速度,我可能建议的另一件事是不要使用表变量。对于大型数据集,临时表通常速度更快,并且可以在需要时建立索引。
One additional thing I might suggest if the other suggestions don't get you enough speed is not to use a table variable. Temp Tables are often faster for large data sets and can be indexed if need be.
更新锁在计算 CTE 所需的时间和更新时间期间保持。 CTE 时间可能导致超时。
将更新目标表所需的锁定时间减少到最短。我建议您创建一个包含两列的临时表。 Col1 是目标表的主键或簇键,Col2 是目标表中所需的值。包装临时表创建并根据事务中的业务逻辑在表中填充值。使用临时表的联接以及单独事务中临时表中的值来更新目标表。更新后删除临时表。
The update lock is being held the time it takes to compute the CTE and the time for the update. The CTE time is probably causing the time out.
To reduce the lock time to the minimum required to update the target table. I suggest you create a temp table with two columns. Col1 is the primary key or cluster key of the target table and Col2 is the value you want in the target table. Wrap the temp table creation and fill the table with values according to your business logic within a transaction. Update the target table using a join to the temp table and the value from the temp table in a seperate transaction. After update drop the temp table.
我认为您应该创建一个 SQL 脚本(或存储过程,如果您要从更高级别使用它),将选择的结果存储到游标中(您只需找到要更新的行的 PatientCartId )然后您应该在更新中使用它,所以答案是肯定的。
测试这一点很容易,您应该将这些命令放入事务中,回滚事务,并且在回滚之前您应该执行选择来测试结果。祝你好运。
I think you should create an SQL script (or stored procedure, if you will use it from a higher level) where you store the results of your selection into a cursor (you'll only have to find the PatientCartId's of the rows to be updated) and then you should use it in your update, so, the answer is yes.
It's easy to test this, you should put these commands into a transaction, rollback the transaction and before the rollback you should perform a selection to test your results. Good luck.