批量插入实体到数据库(Quarkus,Hibernate)

Batch insert entities to DB (Quarkus, Hibernate)

首先:我不习惯 Quarkus 或 Hibernate(我几乎都是 .net)

问题:

我的服务收到约 10k 的列表(我猜这是最常见的数字)。 这是通过资源端点实现的,它需要 +10 秒才能完成,非常长。而且服务没有响应。

*Endpoint -> Service/Business -> DAO*

@Override
public void create(FooBusiness foo) {

    var statuses = new ArrayList<StatusDto>();

    for(var i = 1; i < foo.getFromList().size(); i++){

        var bar = foo.getFromList().get(i);
        statuses.add(new StatusDto(bar.x, bar.y));
    }
    statusDao.create(statuses);
}

statusDao.Create() 注释为 @Transactional:

DAO 是 @ApplicationScoped

而这个 EM 是:

@PersistenceContext
EntityManager entityManager;

statusDao.Create():

@Transactional
public List<StatusDto> create(List<StatusDto> dto) {

    for(var i = 0; i < dto.size(); i++){

        var status = dto.get(i);
        status.setCreatedTimestamp(LocalDateTime.now());
        entityManager.persist(status);
    }

    entityManager.flush();

    return dto;
}

我已经阅读了很多关于此的帖子,其中许多人建议这样做 属性,并将持久循环拆分为与批处理大小相同: quarkus.hibernate-orm.jdbc.statement-batch-size

问题是,当我将它添加到 application.properties 时,我得到了这个 varning:

Cannot resolve configuration item 'statement-batch-size'

我花了将近一天的时间试图找到有关如何加快速度的解决方案,我在这里遗漏了什么明显的问题吗?

And/or:

我可以用某种神奇的方式包装从 servicedao 的调用,而忘记 Quarkus 或 Vert.x 中内置的调用吗?

Hibernate 将您持久化的所有实体保存在持久性上下文中,因此您将获得越来越多的内存,这可能会导致性能不佳。如果您不再需要这些实体,您可以在例如每批 50 件商品。

for (var i = 0; i < dto.size();) {
    var status = dto.get(i);
    status.setCreatedTimestamp(LocalDateTime.now());
    entityManager.persist(status);
    i++;
    if ((i % 50) == 0) {
        entityManager.flush();
        entityManager.clear();
    }
}
entityManager.flush();

很难明确回答这个问题,除非您已经确定响应时间不佳的确切原因。原则上可能是由于:

  1. 与对数据库服务器的许多请求相关的延迟,
  2. 在 Hibernate 有状态会话中将许多实体对象固定在内存中的开销,甚至
  3. 接收和解析传入数据的成本。

我们假设它不是 3。

  • 如果它是 2,那么 JDBC 批处理确实会有所帮助,您只需要弄清楚如何使该配置 属性 起作用。
  • 但我的猜测是克里斯蒂安是正确的,问题是持久化上下文中的数据积累。如果这个猜测是正确的,那么有两种可能的解决方案:一种是使用StatelessSession,它是为这种用法而设计的,另一种是使用flush()clear() ] 正如克里斯蒂安所描述的那样。

我建议使用StatelessSession除非问题实际上是2+3的组合,在这种情况下你需要两者 批处理, 持久性上下文管理,然后在这种情况下执行 Christian 的建议。