插入和不存在的插入之间的性能差异

Posted

技术标签:

【中文标题】插入和不存在的插入之间的性能差异【英文标题】:Performance difference between Insert and Insert Where Not Exists 【发布时间】:2019-05-05 08:10:34 【问题描述】:

我知道使用 INSERT WHERE NOT EXISTS 比使用 INSERT 更好,因为它会导致重复记录或唯一密钥违规问题。 但是在性能方面,它会产生什么大的不同吗?

INSERT WHERE NOT EXISTS 将在内部触发额外的 SELECT 语句来检查记录是否存在。如果是大表,建议使用 INSERT 与 INSERT WHERE NOT EXITS 哪个? 有人请解释两者之间的执行成本差异。

【问题讨论】:

性能主要取决于您一次插入多少行。如果您要插入 BULK 记录,当然会有性能问题,但如果您要插入单行,那没什么大不了的。现在,如果您使用 IF EXISTS,请尝试在 Where 子句中使用的列上应用 Index。 比较数据完整性和性能是一种错误的二分法。您不能仅仅因为加载垃圾的速度更快而损坏您的数据库。 【参考方案1】:

大多数 Oracle IN 子句查询都涉及一系列文字值,当表存在时,标准连接会更好。在大多数情况下,Oracle 基于成本的优化器将为 IN 和 EXISTS 创建相同的执行计划,因此查询性能没有差异。

Exists 关键字计算真或假,但 IN 关键字将比较相应子查询列中的所有值。如果您使用 IN 运算符,SQL 引擎将扫描从内部查询获取的所有记录。另一方面,如果我们使用 EXISTS,SQL 引擎将在找到匹配项后立即停止扫描过程。

当我们想要显示在两个表中都有匹配列的所有行时,使用 EXISTS 子查询。在大多数情况下,这种类型的子查询可以使用标准连接重写以提高性能。

当子查询结果非常大时,EXISTS 子句比 IN 快得多。相反,当子查询结果非常小时,IN 子句比 EXISTS 快。

此外,IN 子句无法将任何内容与 NULL 值进行比较,但 EXISTS 子句可以将所有内容与 NULL 值进行比较。

【讨论】:

您是否有任何关于 Oracle 的“EXISTS 比 IN 快得多”的参考资料?我认为 Oracle 有一个很好的优化器,并且希望性能具有可比性(尽管我个人更喜欢 EXISTS)。 @GordonLinoff - 至少在 Oracle 中,优化器以不同的方式实现 IN 和 EXISTS。因此,当主查询和子查询的相对大小存在显着差异时,选择适当的操作会带来性能优势。 Find out more. @APC 我确信在某些情况下 IN 和 EXISTS 的处理方式不同,但通常我发现他们得到相同的计划。不过,不存在和不存在是两个不同的东西。 @APC 。 . .问题不在于它们是否以相同的方式执行。问题是你是否可以说一个总是比另一个好。 @GordonLinoff - 链接到的文章中的黑天鹅和汤姆凯特都没有说一个总是更好。而是取决于。您要求提供参考,我提供了参考。尽管我同意这些年来对优化器和机器能力的改进使得发现差异很重要的案例变得更加困难。【参考方案2】:

这不是“什么是最快的”的问题,而是“什么是正确的”的问题。

当您将INSERT 放入表中时(没有任何限制),您只需将记录添加到该表中。如果现有的相同记录已经存在,那么这将导致现在有两个这样的记录。这可能没问题,或者这可能是一个问题,具体取决于您的需求 (**)。

当您在INSERT 结构中添加WHERE NOT EXISTS() 时,系统只会将尚未存在的记录添加到表中,从而避免出现多个相同记录的情况。

(**:假设您对目标表有唯一或主键约束,那么重复记录的INSERT 将导致 UQ/PK Violation 错误。如果您的问题是: “什么是最快的:尝试插入行,如果有这样的错误,只需忽略它,而不是尝试在不存在的地方插入()并避免错误”然后我不能给你决定性的答案,但我相当肯定它会是一个近距离的电话。但是我可以说的是 WHERE NOT EXISTS() 方法在代码中看起来会更好,(重要的是!)它也适用于基于集合的操作,try/即使只有 1 条记录导致问题,catch 方法也会在整个集合中失败。)

【讨论】:

【参考方案3】:

INSERT 将根据任何现有架构约束、PK、FK、唯一索引、非空值和任何其他自定义约束检查插入的数据——无论表架构要求什么。如果这些检查正常,则将插入该行并循环到下一行。

INSERT WHERE NOT EXISTS,在上述检查之前,会根据表中所有行的数据检查该行所有列的数据。即使 1 列不同也没关系,然后它会完全按照上面的 INSERT 移动。

性能影响主要取决于: 1. 表中现有行数 2. 行的大小

因此,随着表变大,然后行大小变大,差异就会增大。

【讨论】:

以上是关于插入和不存在的插入之间的性能差异的主要内容,如果未能解决你的问题,请参考以下文章

将现有和不存在的数据框混合插入到 sql

为啥这两个查询之间的性能增益存在差异?

视图和存储过程之间是不是存在性能差异

视图和内联表函数之间是不是存在性能差异?

SVG 属性和样式之间是不是存在性能差异?

C# 中的 ++i 和 i++ 之间是不是存在性能差异?