我有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时)。
session.save(master)
代替每个对象,会更快吗?答案 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">