5

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

所以我的问题是...

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

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

4

7 回答 7

9

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

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

于 2009-02-16T07:30:06.607 回答
7

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

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

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

于 2009-02-16T07:37:57.617 回答
2

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

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

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

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

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

于 2009-02-16T09:01:56.823 回答
1

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

IF (SELECT COUNT(*) FROM X WHERE Y=Z)=0 INSERT INTO (X) VALUES('XX')....

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

于 2009-02-16T07:28:27.077 回答
0

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

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

于 2009-02-16T07:25:12.937 回答
0

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

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

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

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

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

于 2009-02-16T08:26:51.837 回答
0

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

于 2018-10-13T14:31:26.333 回答