Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 休眠关系映射/加速批插入_Java_Mysql_Performance_Hibernate_Orm - Fatal编程技术网

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

Java 休眠关系映射/加速批插入,java,mysql,performance,hibernate,orm,Java,Mysql,Performance,Hibernate,Orm,我有5个MySQL InnoDB表:Test、InputVoice、InputLine、OutputVoice、OutputLine,每个表都在Hibernate中映射和运行。我已经使用了无状态会话/会话和JDBC批处理大小。为了让MySQL处理id生成,我删除了所有生成器类,但它的执行速度仍然很慢。 这些表中的每一个都用java类表示,并相应地映射到hibernate中。当前,当需要写出数据时,我循环遍历对象并执行session.save(Object)或session.insert(Obje

我有5个MySQL InnoDB表:
Test、InputVoice、InputLine、OutputVoice、OutputLine
,每个表都在Hibernate中映射和运行。我已经使用了无状态会话/会话和JDBC批处理大小。为了让MySQL处理id生成,我删除了所有生成器类,但它的执行速度仍然很慢。 这些表中的每一个都用java类表示,并相应地映射到hibernate中。当前,当需要写出数据时,我循环遍历对象并执行
session.save(Object)
session.insert(Object)
(如果我使用的是无状态会话)。当我的行数达到最大jdbc批处理大小(50)时,我也会进行刷新和清除(在使用会话时)

  • 如果我把它们放在一个包含对象的“父”类中,并执行
    会话。save(master)
    ,而不是每一个,会更快吗
  • 如果它们位于master/container类中,我将如何在hibernate中映射它们以反映这种关系?容器类实际上不是它自己的表,而是一个基于两个索引run_id(int)和line(int)的关系
  • 另一个方向是:如何让Hibernate执行多行插入

  • ID生成策略对于Hibernate中的批插入至关重要。特别是,身份生成通常不起作用(请注意,自动通常也映射到身份)。这是因为在批插入过程中,Hibernate有一个名为“RequiredimmediatedAccess”的标志,表示是否立即需要生成的ID;如果是,则禁用批处理

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

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

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

    此外,以下属性对于实现批插入非常重要。我不敢说它们是必需的,因为我不是足够的Hibernate专家来这样做——也许这只是我的特殊配置——但根据我的经验,它们是必需的:

    hibernate.order_inserts = true
    hibernate.order_updates = true
    
    这些属性的文档记录得非常糟糕,但我相信它们所做的是使SQL INSERT和UPDATE语句能够正确地分组以进行批处理执行;我想这可能是你想要的多行插入。如果我在这件事上错了,别开枪,我在回忆

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

    hibernate.jdbc.batch_size = xx
    

    其中xx自然是您所需的批次大小。

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

    hibernate.order_inserts = true
    hibernate.order_updates = true
    
    • 我从使用
      会话更改为
      
      无状态会话

    • 重新订购 处理所有元素的Java代码 在批处理中,一次创建一个表。那么全部 先是表x,然后是表y,等等

    • 已从每个文件中删除
      班级。Java现在创建了它,并且 将其指定给对象

    • 创建的逻辑允许我确定 正在设置id,但未写入 数据库的“空”行

    • 最后,我打开了
      dynamic insert
      我的班级在冬眠 类似这样的定义:


    @JDR:非常感谢您提供的所有信息-我正在将我的ID生成更改为本机(这是否也会禁用批处理?),并将添加您的其他想法。我已经有jdbc.batch\u size=50,但没有订单插入/更新。我会让您知道它的工作情况。@JDR:我实现了您的建议,我可以看到它正在将我的插入分组,以便按顺序插入所有表。它插入了所有的测试,然后是所有的等等。。它告诉我批量大小是50-这是好的。但我仍然获得了与以前大致相同的性能—对于3300条记录,这大约是5分钟(请记住,每条记录意味着一次插入到5个不同的表中)。@manyxcxi:由于RequiremeMediatedAccess变量(使用H2和Hibernate 3.5.1-Final),将ID更改为本机禁用的批处理。如果批处理程序说它正在执行50个批处理,那么这就是它正在做的,这就是这里的目标。5分钟的3300条记录似乎有点过分,我可以在大约一秒钟内插入1000条记录,甚至还有一些额外的Hibernate搜索开销(尽管是在嵌入式H2数据库上)。你有一些输出日志样本吗?您运行的是什么数据库,使用的是什么连接池?我使用的是MySQL(表是InnoDB),但我弄错了。5分钟是整个跑步所需的时间。有很多处理开销,事实上,我会冒险猜测,多达90%的开销是我无法控制的(等待来自单独计算引擎的响应)。总体思路是:从CSV中一次读取500行,转换成程序特定的对象,发送到计算器,处理响应对象,转换成数据库对象,写回批处理。我会努力清理日志以供展示我忘了提到,我偏离了计划,没有使用发电机。我的java代码为每个表分配一个id,这样Hibernate就不必处理它了