gpt4 book ai didi

java - 为什么在 Oracle 上使用 Hibernate 批量插入数据对于较大的事务要慢得多?

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:23:27 25 4
gpt4 key购买 nike

我当前的项目包括一个归档功能,可以将内存数据库中的数据传输到关系数据库。

我从内存数据库流式传输结果,创建 hibernate 实体并将数据以 5000 个为一批保存到数据库。这些实体有几个关系,因此我将每个实体写入不同的表。

作为引用,您可以假设在整个归档过程中执行了 100 万次插入查询。

这个过程一开始真的很慢,所以我在网上查找并实现了一些使用 Hibernate 批量编写的常见建议:

  • 我将 hibernate.jdbc.batch_size 设置为合适的大小并将 hibernate.order_inserts 设置为 true。
  • 为了防止内存问题,我时不时地刷新并清除 hibernate session 。

这是批处理的一个小例子:

RedisServiceImpl.Cursor<Contract> ctrCursor = contractAccessService.getCursor("*", taskId);

Iterators.partition(ctrCursor, BATCH_SIZE).forEachRemaining(chunk -> {

portfolioChunkSaver.saveContractChunk(chunk, taskId);

em.flush();
em.clear();
});

ctrCursor.close();

这个过程有效,但速度非常慢。在 Oracle 中插入 100 万条记录大约需要 2 个小时才能完成,即每秒约 2.5 个查询。

目前,整个归档功能都包含在 1 个事务中,这感觉根本不对。最大的好处是您可以确定存档是否成功完成,而无需为此提供一些额外的检查系统。 (一切都在数据库中或不在数据库中)

作为加速实验,我修改了代码,为每个实体 block (5000) 创建一个数据库事务,而不是将所有内容都包装在一个大事务中。

这一变化产生了巨大的影响,现在的速度大约是以前的 10-15 倍。

在进行性能分析时,我在更改前看到了这种行为:

Before: 
Java - very low CPU
Oracle - very high CPU, low disk write activity

After:
Java - high CPU
Oracle - Low CPU, very high disk write activity

第二个行为很有意义,java 正在发送尽可能多的查询,数据库服务器受到本地系统磁盘写入速度的限制。

我的问题来了:为什么影响这么大?当我在更大的交易中发送所有内容时,Oracle 有何不同之处?

作为旁注:我从来没有遇到过 MySQL 的这个问题,所以 Oracle(或 oracle JDBC 驱动程序)一定是以不同的方式做某事。

我可以想象保证 ACID 合规性会导致开销,但我不希望出现这种巨大的速度差异。

最佳答案

您应该确保您有足够的 UNDO 空间(也称为 UNDO 段),因为大型事务会消耗大量空间。

When a ROLLBACK statement is issued, undo records are used to undo changes that were made to the database by the uncommitted transaction.

最好只在完成数据完整性时才提交,并且经过适当调整的 Oracle 数据库可以支持大型事务而不会出现任何性能问题。

关于java - 为什么在 Oracle 上使用 Hibernate 批量插入数据对于较大的事务要慢得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49170253/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com