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

时间:2010-04-22 20:16:07

标签: java mysql performance hibernate orm

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

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

2 个答案:

答案 0 :(得分:14)

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

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

通常执行工作的生成策略是TABLE和SEQUENCE,因为Hibernate可以预先生成ID,从而允许批量插入。

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

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

hibernate.order_inserts = true
hibernate.order_updates = true

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

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

hibernate.jdbc.batch_size = xx

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

答案 1 :(得分:7)

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

hibernate.order_inserts = true
hibernate.order_updates = true
  • 我从使用Session更改为 StatelessSession

  • 重新订购了 用于处理所有元素的Java代码 一次一张表。所以 表x,然后表y等

  • 从每个中删除<generator> 类。 Java现在创建它和 将其分配给对象

  • 创建逻辑,让我可以确定是否 正在设置id而不是写入 '空'到数据库的行

  • 最后,我打开了dynamic-insert 我的课程在他们的休眠状态 像这样的定义:<class name="com.my.class" table="MY_TABLE" dynamic-insert="true">