【问题标题】:Spring Data JPA findAllById with 10K id's具有 10K id 的 Spring Data JPA findAllById
【发布时间】:2020-04-24 03:40:33
【问题描述】:

我有 10k 个 ID,需要从数据库中获取所有记录,但 findAllById 抛出 stack overflow 并且无法完成事务。

我该如何解决这个问题?

//itemsList has 10k records in csv format
List<Item> items = factory.getIemRepository().findAllById(itemsList);

【问题讨论】:

  • 不要试图在一个查询中获取所有对象,而是分批处理它们,而不是例如每个 100 个对象。
  • 快速猜测一下,您是否使用SELECT * FROM ... WHERE id IN (...) 作为查询。 IN 命令对许多实现都有限制,这意味着它不能超过(我认为)4k 个元素。你可以查询到WHERE id = ... OR id = ... OR ...,或者像上面建议的那样批量处理。

标签: java spring spring-boot spring-data-jpa


【解决方案1】:

说finaAllXXXX() 不是一个好方法。我们应该执行更具体的条件库查询或使用分页。增加内存不是解决办法,因为数据会逐渐增加。

https://www.baeldung.com/spring-data-jpa-pagination-sorting

【讨论】:

    【解决方案2】:

    根据您的数据库,大多数数据库都会限制您一次可以查询的 ID 数量。假设 10k 未超过您的特定数据库的此限制,您提到的 stackoverflow 很可能是因为您返回 10k 结果并且您的系统内存不足。

    尝试增加 Java 的堆空间。例如,

    mvn spring-boot:run -Drun.jvmArguments="-Xmx1024m" -Drun.profiles=dev
    

    参考:How can I configure the heap size when starting a Spring Boot application with embedded Tomcat?

    【讨论】:

      【解决方案3】:

      您可以在您的存储库中创建一个带有查询 WHERE id IN (:ids) 的方法,并像这样调用它:

      private List getEdcsByEdcCodes(Collection<Long> idslist) {
          final int chunkSize = 500;
          final AtomicInteger counter = new AtomicInteger();
      
          Collection<Collection<Long>> devidedIdsList = edcCodes.stream()
              .collect(Collectors.groupingBy(resultList -> counter.getAndIncrement() / chunkSize))
              .values();
      
          return devidedIdsList.stream()
              .map(idsList -> findbyIdList(idsList))
              .flatMap(List::stream)
              .collect(Collectors.toList());
      }
      

      【讨论】:

        【解决方案4】:

        findAllById 将生成带有 IN 子句的 SQL 语句(即 where ID in (val1, val2, ... val10000)。

        这会导致 Oracle(最多 1000 个)和其他 DB 中的错误。如果不是,它可能会使用所有可用内存来存储 ID 列表。

        有多种选择,但我建议将 10k ID 存储在临时表中并与主表执行 SQL 连接。这将比任何批处理或在多个子查询中中断查询执行得更好。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-08-19
          • 2019-04-22
          • 2020-08-18
          • 1970-01-01
          • 1970-01-01
          • 2018-11-24
          • 2017-06-07
          • 1970-01-01
          相关资源
          最近更新 更多