2010-04-22 102 views
7

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

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

我忘了提,每个这些表中有很多列 – ashurexm 2010-04-23 00:28:48

回答

7

对我来说,最终的解决方案是使用voetsjoeba的回应作为跳板点。 我的休眠配置使用以下选项:

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">

14

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

当它说“立即执行标识插入”时,您可以很容易地在DEBUG级日志中发现它 - 这意味着它已经跳过了批处理,因为它被告知生成的ID在插入后立即需要。

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

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

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

hibernate.order_inserts = true 
hibernate.order_updates = true 

这些属性相当差的记录,但我相信他们所做的是使SQL INSERT和UPDATE语句正确分组以便批量执行;我认为这可能是你之后的多行插入。如果我错了,不要拍我,我从记忆中回忆起来。

我还会继续并假设您设置了以下属性;如果不是,这应该作为提醒:

hibernate.jdbc.batch_size = xx 

其中xx是您希望的批量大小,当然。

+0

@JDR:非常感谢所有这些信息 - 我正在将我的ID生成更改为本机(这是否会禁用批处理?),并会添加您的其他想法。我已经有jdbc.batch_size = 50,但没有order_inserts/updates。我会让你知道它的工作效果。 – ashurexm 2010-04-22 21:50:41

+0

@JDR:我实现了你的建议,我可以看到它将我的插入组合在一起,所以所有的表都按顺序插入。它插入所有的测试,然后是所有的等.. 它显示我的批量大小是50-这是很好的。 但是我仍然获得了与之前大致相同的性能 - 这对于3300条记录约为5分钟(请记住,每条记录意味着一个插入到5个不同的表中)。 – ashurexm 2010-04-22 23:18:05

+1

@manyxcxi:由于requireImmediateIdAccess变量(使用H2和Hibernate 3.5.1-Final),将ID更改为原生残疾人批处理。如果配料商说它正在执行50个批次,那么这就是它正在做的事情,这是这里的目标。 5分钟3300条记录似乎有点过分,我可以在大约一秒钟内插入1000条记录,甚至有一些附加的Hibernate搜索开销(尽管在嵌入式H2数据库中)。我可以在任何地方看到一些示例输出日志吗?你正在运行什么数据库以及你使用了哪个连接池? – voetsjoeba 2010-04-22 23:22:26