从 Id 中删除 @GeneratedValue 对性能有什么影响

What's the effect of removing @GeneratedValue from the Id on the performance

我正在开发一个 RCP 应用程序,它使用 Rest 与 Tomcat- 服务器通信。由于我们获得了越来越多的数据,load/copy-routines 正缓慢但坚定地变得过时。有时我需要几分钟来执行一些复制操作。所以我正在寻找一些建议,如何加快我的例程。

以下是我使用的技术:

  1. RCP 客户端(e4 平台)
  2. Tomcat8 台服务器
  3. Oracle-DB
  4. JDBC 作为 API 和 Hibernate
  5. 休息

第一件事。我检查了实体,几乎所有实体看起来都像下面的代码

@Entity
@SequenceGenerator(name = "CHECKITEM_SEQ", sequenceName = "CHECKITEM_SEQ", allocationSize = 1)
public class CheckItem extends AbstractTreeNode implements Serializable,Cloneable {...}

我想通过复制数据(大多数时候每次操作超过 200K)因为我将它们用作主键,

@Id
@GeneratedValue(generator = "CHECKITEM_SEQ", strategy = GenerationType.SEQUENCE)
    public Integer getId() {
        return id;
    }

DB 必须为每个对象生成一个序列并检查其上的约束,所以我想知道如果我删除序列我会获得多少性能,因为我并不真正 use/need 它们在D B。现在我的问题:

  1. 有什么反对删除数据库中的约束(在这种特殊情况下是主键)吗?
  2. 有没有人more/better建议如何为此类操作提高数据库的性能?
  3. 我可以有教程或文档来帮助我完成这个过程吗?

我希望,我已经足够清楚了,我将不胜感激任何帮助。已经谢谢了。

使用 @GeneratedValue 标识符的问题在于,为了让 Hibernate 将新实体放入持久性上下文(一级缓存)中,它必须知道标识符。因此,当您使用基于 IDENTITYSEQUENCE 的标识符时,这可能会影响 JDBC 驱动程序能够充分批量插入操作。

例如,您说明大多数实体使用以下序列生成:

@SequenceGenerator(
   name = "CHECKITEM_SEQ", 
   sequenceName = "CHECKITEM_SEQ", 
   allocationSize = 1)

因此,每当对实体进行持久化操作时,您就是在告诉序列生成器只生成一个值,因此 JDBC 通信如下所示:

1. Get Next Sequence
2. Insert
3. Get Next Sequence
4. Insert
5. Get Next Sequence
6. Insert

如此处所示,我们无法批处理插入操作,因为我们必须在插入操作发生之前获取每个插入操作的标识符。最小化这种影响并处理批量插入的一种解决方案是使用更大的 allocationSize.

1. allocationSize=10 -> Get Next 10 sequences
2 - 11. Perform 10 inserts in batch
Repeat

正如您在此处看到的那样,驱动程序可以批量执行 10 次插入,Hibernate 以 10 次为单位批量分配序列,因此插入速度更快。

显然这有一个小缺点,如果你分配了 10 个序列,但剩下的批次只需要插入 6 个实体;您已经浪费了 4 个序列值,但是您可以通过支持执行 jdbc 批量插入来获得性能。

下一个合乎逻辑的步骤是确定您是否可以完全消除对 @GeneratedValue 的使用,因为这将为您的复制操作提供批量插入的最佳性能;但是,您的数据模型可能无法做到这一点。在过去处理大量数据移动时,我尝试根据数据中的自然键定义主键,如果可能的话不涉及代理键。

欢迎阅读有关 JDBC 批处理操作的更多信息 here