有没有人发现在 sql server 2008 中使用 BEGIN TRY..END TRY 与旧的 IF @@ERROR <> 0 相比有任何性能提升/折衷?只是想知道是否存在性能损失。
6 回答
由于数据库磁盘命中问题是相同的,因此应该没有明显的性能问题。
从 SQL 2005 开始,您应该尝试使用 TRY CATCH 方式来处理异常或记录错误。它被认为是最佳实践。使用它应该不会对性能造成重大影响。
BEGIN TRY
BEGIN TRANSACTION
-- SQL
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK
SELECT
ERROR_MESSAGE(),
ERROR_NUMBER() -- etc
END CATCH
这是一个老问题,但在 2012 年,Aaron Bertrand 写了一篇详细的文章Performance Impact of different error handling techniques,他比较了 SQL Server 中处理异常的几种方法,我认为这里值得一提。
他说,人们用来处理异常的主要方法是:
- 只需让引擎处理它,并将任何异常返回给调用者。
- 使用
BEGIN TRANSACTION
和ROLLBACK
如果@@ERROR <> 0
。- 在块中使用
TRY/CATCH
with (SQL Server 2005+)。ROLLBACK
CATCH
许多人采取的方法是,他们应该首先检查他们是否会发生违规,因为自己处理重复项似乎比强迫引擎去做更干净。
他的结论是:
如果我们认为我们的故障率很高,或者不知道我们的潜在故障率是多少,那么首先检查以避免引擎中的违规行为将非常值得我们花时间。即使在我们每次都成功插入的情况下,首先检查的成本也是微不足道的,并且很容易通过以后处理错误的潜在成本来证明(除非您的预期失败率恰好是 0%)。
这是文章中的图表:
CheckInsert | Checks `IF EXISTS` first | Simple `INSERT`
CheckRollback | Checks `IF EXISTS` first | Use `IF @@ERROR <> 0`
CheckTryCatch | Checks `IF EXISTS` first | Use `TRY CATCH`
JustInsert | | Simple `INSERT`
JustRollback | | Use `IF @@ERROR <> 0`
JustTryCatch | | Use `TRY CATCH`
忘记性能吧,这该死的景象更安全、更好、更可预测。
但是,使用@@ERROR 通常需要一个 GOTO 和/或大量 IF 语句才能正确管理它,所以我猜想 TRY..CATCH 可能会有微小的提升。
在没有错误的情况下,TRY ... CATCH 的性能很可能会多一点。另一方面,在许多有错误的情况下,它会更快。
但是,无论如何,您都不应该为性能而严格编码。而且,开销(如果有的话)将会相当小,所以在这种情况下我不会为了性能而牺牲更安全的语法。
此外,Try ... Catch 使代码更易于维护,特别是如果您的 SQL 开发团队使用 SQL Server 的时间不长,不幸的是,这种情况经常发生。我想几年后这种情况会更多。