在单个事务中插入多行时 Oracle 查询性能下降

Posted

技术标签:

【中文标题】在单个事务中插入多行时 Oracle 查询性能下降【英文标题】:Oracle query performance degrades when inserting many rows in a single transaction 【发布时间】:2013-03-21 10:52:18 【问题描述】:

在单个事务中,我将可能的行插入到表中,在插入行之前,我执行查询以查看是否已经存在具有我要插入的键的行。

我看到的是,检查密钥是否存在的查询在我的事务中变得非常慢,但从另一个事务中它很快,在下一个事务中它很快。

我无法将这项工作分解为更小的事务,因为我正在处理的请求需要在单个事务中。

我可以做些什么来使这个事务中的选择查询快速?

【问题讨论】:

为什么要检查该行是否已经存在?创建唯一约束(或索引)并简单地处理错误。 是的,a_horse_with_no_name 是对的。为什么要复制效率大大提高的内置功能! 使用merge 避免插入重复项。 您可以创建唯一约束或索引/主键(如@a_horse_with_no_name 所述)。另外,请尝试找出花时间的东西-您的选择或插入。也许您应该为您选择的字段添加索引 @Greg - 没有足够的信息来帮助你。检查行是否存在或插入部分的查询有问题吗?你如何检查行是否存在?如果插入有问题,那么您是否尝试过合并、条件插入、添加附加提示等...信息不足。 【参考方案1】:

所以,请添加约束/主键。这将允许您删除所有选择。 可以考虑使用@Egor_Skriptunoff 推荐的MERGE。

或为您选择的列添加索引。

【讨论】:

我在我选择的列上有索引。我不能等待约束冲突异常,因为我正在使用休眠,一旦出现数据库错误,我必须回滚事务并重新开始。 我不认为我可以使用合并,因为 Hibernate 正在生成 SQL。 我不熟悉Hibernet,但是你能在Store Procedure中运行你的事务吗?如果是这样,您将能够使用合并,并以您的方式处理约束违规。这可以帮助存储过程:mkyong.com/hibernate/how-to-call-store-procedure-in-hibernate【参考方案2】:

如果首先插入数百万条记录是进行增量提交,因为您可能会遇到临时空间碎片或限制,从而导致速度减慢。可以在开始结束块中完成 此外,这允许您通过

添加索引
create index b indexName on table_name(col1, col2, col3);

如之前的答案所述,合并速度更快。 或者添加所有忽略重复然后删除重复 这可以通过 例如

begin
    insert into table_name select * from table_name; [ if pulling from another table]or[use values and column maps]
    delete from table_name A where rowid >(select min(rowid) from table_name B where A.key_value=B.key_value);
end

如果在一个过程中这也需要 查询和删除都可以在开始结束块中并立即执行('you ddl statement here';');

【讨论】:

以上是关于在单个事务中插入多行时 Oracle 查询性能下降的主要内容,如果未能解决你的问题,请参考以下文章

从 oracle 12c 升级到 oracle 19c 导致查询性能下降

MySQL ON DUPLICATE KEY UPDATE 在单个查询中插入多行

PDO Prepared在单个查询中插入多行

如何使用 SQL Server 中的存储过程在单个查询中插入多行

在单个 INSERT 查询中插入多行会保证顺序自动递增主键吗?

Oracle中的多行插入查询(从一张表中选择多行并插入到另一张表中[重复]