SQL 性能 - 更好地插入和引发异常或检查是不是存在?

Posted

技术标签:

【中文标题】SQL 性能 - 更好地插入和引发异常或检查是不是存在?【英文标题】:SQL Performance - Better to Insert and Raise Exception or Check exists?SQL 性能 - 更好地插入和引发异常或检查是否存在? 【发布时间】:2010-10-07 20:07:21 【问题描述】:

我正在考虑对我的代码中特别重要的部分进行优化。 它的任务是将统计数据插入表中。其他程序对这些数据的影响相当大。否则我会考虑使用 SQL 批量插入等。

所以我的问题是……

是否可以尝试插入一些数据,因为知道它可能(不太经常)为重复行抛出 SqlException?

异常对性能的影响是否比插入前检查每一行更糟糕?

【问题讨论】:

【参考方案1】:

在高负载并发环境中,检查内容是否存在是不够的,因为会有竞争条件,并且行将插入到其他存在检查之间。 所以你要么必须做一个检查后锁定(它本身很容易出现竞速条件),要么再次处理异常以防其他数据能够潜入。

【讨论】:

【参考方案2】:

我不认为存储过程会加速单例插入,除非涉及其他处理。可能还有其他好处 - 将所有逻辑保持在一个位置等。

如果有重复等,我个人会插入并捕获错误。

如果您执行 IF NOT EXISTS 检查然后有条件地 INSERT,则事务需要持有一个锁的时间间隔,这可能会增加对表的阻塞。

对于繁忙的插入表,值得检查表的碎片程度。如果您在 Identity / Auto-number 列上使用聚集 PK 插入,则所有插入都在一端(并且索引可以具有 100% 的填充因子),但如果插入在整个聚集索引中是随机的,那么您可能会出现页面拆分等问题。

一个相关的问题是表上的统计信息可能很快就会过时,这可能会影响使用缓存查询计划等的查询的性能。

【讨论】:

【参考方案3】:

可能与这里的问题不太相关。

但我在一个项目中工作,在以编程方式删除表之前,它用于检查表是否存在。

当我们开始优化代码时,我们将其更改为处理特定的异常,而不是在删除表之前检查表是否存在。

而且我们在时间上有相当多的改进,因为我们在流程中多次使用存在性检查。

按照这种思路,我认为处理异常而不是另一个数据库查询进行检查的成本更低。

【讨论】:

【参考方案4】:

在纯粹的性能级别上,插入数据并处理错误会更快,尤其是在错误不常见的情况下。运行一个选择查询来检查重复,处理该结果,如果成功则插入,这将比插入和处理偶尔的错误慢得多。如果它引发异常,那么会慢一些,因为在大多数语言中异常处理都很慢,但是处理异常将比任何语言的 SQL 查询快很多倍。

正如 Assaf 所说,通常还有一种方法可以显式处理重复项,这样您就可以完全避免该错误。这将进一步提高性能,并允许您明确表明您正在以特定方式处理重复项。

是否使用存储过程取决于您 - 它可以帮助提高性能,但代价是在数据库中添加更多逻辑。这是你必须做出的决定。我在这方面有过不好的经历,但这取决于 RDBMS 和您使用的语言。

【讨论】:

【参考方案5】:

首先,我的建议是在正确性方面犯错,而不是在速度方面犯错。当您完成项目并且分析显示您在插入行之前检查是否存在大量时间,只有然后对其进行优化。

其次,我认为如果所有 RDBMS 中都存在重复项,则存在插入和跳过的语法,因此这首先应该不是问题。我尽量避免将异常作为正常应用程序流程的一部分,并将它们留给真正的例外情况。也就是说,不要指望数据库中的异常来解决代码中的逻辑问题。在您的端(代码)上保持尽可能多的一致性,并让 DB 异常仅指示真正的错误。

【讨论】:

一些 DBMS 平台有一个合并命令可以执行此操作,但并非所有平台都执行此操作。 晚了 11 年,但对于遇到此问题的其他人......我最初正在处理异常并继续进行一些异步插入。发现在重复插入时处理异常而不是首先检查会消除我所拥有的任何异步好处。【参考方案6】:

我认为最好使用存储过程,并使用 IF

IF (SELECT COUNT(*) FROM X WHERE Y=Z)=0 插入 (X) 值('XX')....

您可以添加一个 ELSE 条件...

【讨论】:

NOT EXISTS 总是(应该)比 COUNT 快。 是的,EXISTS 测试不仅会比 COUNT() 快,而且在大表上 COUNT() 会很慢,即使列被索引【参考方案7】:

是的,我会一直检查。例如电子邮件地址或 IP 地址。

如果您担心性能问题,请使用存储过程来处理重复的逻辑。

【讨论】:

以上是关于SQL 性能 - 更好地插入和引发异常或检查是不是存在?的主要内容,如果未能解决你的问题,请参考以下文章

SQL FK 和预检查是不是存在

Unity 单元测试 - 检查带有参数的函数调用是不是引发异常

引发异常或引发异常()

PL/SQL 异常和错误处理

为啥抛出异常比返回错误代码更好?

性能更好的 SQL 查询