休眠关系映射/加速批量插入

ash*_*exm 7 java mysql performance orm hibernate

我有5个MySQL InnoDB表:Test,InputInvoice,InputLine,OutputInvoice,OutputLine每个表都映射并在Hibernate中运行.我使用过StatelessSession/Session和JDBC批量大小.我删除了任何生成器类,让MySQL处理id生成 - 但它仍然执行速度很慢.这些表中的每一个都在java类中表示,并相应地映射到hibernate中.目前,当需要将数据写出来时,我遍历对象并执行session.save(Object)或者session.insert(Object)如果我正在使用StatelessSession.当行数达到最大jdbc批量大小(50)时,我也会执行刷新和清除(使用Session时).

  1. 如果我在一个"父"类中拥有这些对象而session.save(master)不是每个对象,它会更快吗?
  2. 如果我在主/容器类中使用它们,我如何在hibernate中映射它以反映这种关系?容器类实际上不是它自己的表,而是一个基于两个索引run_id(int)和line(int)的关系.
  3. 另一个方向是:如何让Hibernate进行多行插入?

voe*_*eba 14

ID生成策略对于Hibernate中的批量插入至关重要.特别是,身份生成通常无法正常工作(注意,AUTO通常映射到IDENTITY为好).这是因为在批量插入期间,Hibernate有一个名为"requiresImmediateIdAccess"的标志,表示是否立即生成ID; 如果是,则禁用批处理.

您可以在DEBUG级日志中轻松发现"立即执行标识插入" - 这意味着它已跳过批处理,因为它被告知插入后需要立即生成ID.

生成策略通常的工作是表和序列,因为Hibernate可以预先生成的ID,从而允许批量插入.

快速查看批量插入是否有效的方法是激活DEBUG级日志,因为BatchingBatcher将明确告诉您正在执行的批量大小("执行批量大小:"+ batchSize).

此外,以下属性对于实现批量插入很重要.我不敢说他们是必需的,因为我不够Hibernate专家这么做 - 也许这只是我的特殊配置 - 但根据我的经验,他们仍然需要:

hibernate.order_inserts = true
hibernate.order_updates = true
Run Code Online (Sandbox Code Playgroud)

这些属性记录很差,但我相信他们所做的是使SQL INSERT和UPDATE语句能够正确分组以进行批处理执行; 我想这可能是你想要的多排插页.如果我错了,请不要开枪,我从记忆中回忆起来.

我也会继续假设您设置以下属性; 如果没有,这应该作为提醒:

hibernate.jdbc.batch_size = xx
Run Code Online (Sandbox Code Playgroud)

其中xx是您所需的批量大小,当然.


ash*_*exm 7

我的最终解决方案是使用voetsjoeba的响应作为跳跃点.我的hibernate配置使用以下选项:

hibernate.order_inserts = true
hibernate.order_updates = true
Run Code Online (Sandbox Code Playgroud)
  • 我从使用Session改为 StatelessSession

  • 重新排序Java代码以一次处理批处理表中的所有元素.所有表x,然后表y等.

  • <generator>从每个班级中删除了.Java现在创建它并将其分配给对象

  • 创建的逻辑允许我确定是否只是设置了一个id而不是将"空"行写入数据库

  • 最后,我dynamic-insert 在他们的hibernate定义中打开了我的类,如下所示:<class name="com.my.class" table="MY_TABLE" dynamic-insert="true">