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时).
session.save(master)不是每个对象,它会更快吗?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是您所需的批量大小,当然.
我的最终解决方案是使用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">