【问题标题】:Bulk insert/update using Stateless session - Hibernate使用无状态会话批量插入/更新 - 休眠
【发布时间】:2016-06-24 10:40:10
【问题描述】:

我需要在 3 个表中插入/更新超过 15000 行。所以这是 45k 总插入。

在网上阅读后我在hibernate中使用了Statelesssession,它最适合批处理,因为它没有上下文缓存。

session = sessionFactory.openStatelessSession;
for(Employee e: emplList) {
  session.insert(e);
}
transcation.commit;

但是这段代码需要一个多小时才能完成。

有没有办法一次性保存所有实体对象? 保存整个集合而不是一个一个地做?

编辑:是否有任何其他框架可以提供快速插入?

干杯!!

【问题讨论】:

  • 你尝试过hibernate.order_insertshibernate.order_updates 的简单会话吗?你能否展示一下当你保存一个 Employee 时执行了哪些 SQL 语句?

标签: java hibernate


【解决方案1】:

您应该阅读 Vlad Mihalcea 的这篇文章:

How to batch INSERT and UPDATE statements with Hibernate

【讨论】:

  • 根据文章说我需要使用batch_size,但是插入需要同样的时间。
【解决方案2】:

你需要确保你已经设置了休眠属性:

hibernate.jdbc.batch_size

这样 Hibernate 可以批处理这些插入,否则它们将一次完成一个。

【讨论】:

  • 我在正常会话中厌倦了这个,它仍然需要相同的时间或关闭。
【解决方案3】:

没有办法一次性插入所有实体。即使您可以在内部执行session.save(emplList) 之类的操作,Hibernate 也会一一保存。

根据 Hibernate 用户指南 StatelessSession 不要使用批处理功能:

StatelessSession 接口定义的 insert()、update() 和 delete() 操作直接对数据库行进行操作。它们导致相应的 SQL 操作立即执行。它们与 Session 接口定义的 save()、saveOrUpdate() 和 delete() 操作具有不同的语义。

改为使用普通 Session 并不时清除缓存。实际上,我建议您先测量您的代码,然后进行更改,例如使用 hibernate.jdbc.batch_size,这样您就可以看到任何调整对负载的改善程度。

尝试像这样改变它:

session = sessionFactory.openSession();
int count = 0;
int step = 0;
int stepSize = 1_000;
long start = System.currentTimeMillis();
for(Employee e:emplList) {
    session.save(e);
    count++;
    if (step++ == stepSize) {
        long elapsed = System.currentTimeMillis() - start;
        long linesPerSecond = stepSize / elapsed * 1_000;
        StringBuilder msg = new StringBuilder();
        msg.append("Step time: ");
        msg.append(elapsed);
        msg.append(" ms Lines: ");
        msg.append(count);
        msg.append("/");
        msg.append(emplList.size());
        msg.append(" Lines/Seconds: ");
        msg.append(linesPerSecond);
        System.out.println(msg.toString());
        start = System.currentTimeMillis();
        step = 0;
        session.clear();
    }
}
transcation.commit;

关于hibernate.jdbc.batch_size - 您可以尝试不同的值,包括一些非常大的值,具体取决于使用的底层数据库和网络配置。例如,对于应用服务器和数据库服务器之间的 1gbps 网络,我确实使用了 10,000 的值,这给了我每秒 20,000 条记录。

stepSize 更改为与hibernate.jdbc.batch_size 相同的值。

【讨论】:

  • 所以基本上你是说我不能减少这么多插入所花费的时间。有没有其他框架提供这样的功能?
  • 没有。因为它是基于jdbc的。
  • 您可以使用批量 jdbc 批量插入使其更快。只需使用普通的 Hibernate 会话并更改 hibernate.jdbc_batch_size
  • 我试过这个。它仍然需要几乎与使用无状态会话插入相同的时间。
猜你喜欢
  • 2015-09-08
  • 2015-08-01
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多