java - 如何在单个 JDBC 连接中执行多个 JPA 查询

标签 java hibernate spring-boot jpa connection-pool

在 Spring-boot 应用程序中,我将 JPA 与 Hibernate 结合使用。

我有一个自定义选择查询方法,带有在 JPA 存储库中定义的参数化 IN 子句。由于数据很大,我使用小批量的 ID 作为参数传递相同的查询多次。但我无法提高性能。

大约有200000条记录,耗时1分钟。这是非常巨大的。

以下是我厌倦的事情

  1. 仅选择所需的列,而不是整个 POJO -> 确实将查询时间减少了 8 秒
  2. 当我分析 Hibernate 静态时:以下是找到的日志:

    (获取 1 个 JDBC 连接花费了 382016470 纳秒; 释放 0 个 JDBC 连接花费了 0 纳秒; 准备 1 条 JDBC 语句花费了 798909958 纳秒; 执行 1 个 JDBC 语句花费了 305523944 纳秒; 执行 0 个 JDBC 批处理花费了 0 纳秒; 执行 0 个 L2C put 花费了 0 纳秒; 执行 0 次 L2C 命中花费了 0 纳秒; 执行 0 次 L2C 未命中花费了 0 纳秒; 执行 0 次刷新花费了 0 纳秒(总共刷新 0 个实体和 0 个集合); 执行 0 次部分刷新(总共刷新 0 个实体和 0 个集合)花费了 0 纳秒

即使使用 Hikari 连接池,创建 JDBC 连接也需要时间。以下是 hikari 属性

 spring.datasource.hikari.connection-timeout=120000
    spring.datasource.hikari.maximum-pool-size=100
    spring.datasource.hikari.minimum-idle=30
 spring.jpa.hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider
    spring.datasource.hikari.pool-name=HikariConnectionPool
    spring.datasource.hikari.data-source-properties.cachePrepStmts=true
    spring.datasource.hikari.data-source-properties.useServerPrepStmts=true
  • 并为每个 jpa 查询建立 JDBC 连接,做好准备。 即使设置了以下属性后

    spring.datasource.hikari.data-source-properties.cachePrepStmts=true spring.datasource.hikari.data-source-properties.useServerPrepStmts=true

  • 我将 IN 子句的参数数量保持不变

    代码片段

    //JPA Reposistry
    
    public interface CarRepository extends CrudRepository<Car, String>, JpaSpecificationExecutor<Car> {
    
    @Query(SELECT u.carName as carName,
        u.carId as
        carId from
        Car u
        where u.carId in (:carIds))
    List<CarP> findCarProjections@Param("carIds")Set<String> carIds);
    
    }
    
    //Service
        @Component public carService
    
    {
    @Autowired
    CarRepository carRepo;
    
    public void processCars(List<carId> carIds)
    {
    
    List<List<String>> carIdPartioned = partionCarIds(carIds)
    ExecutorService es = Executors.newFixedThreadPool(10);
    for(List<String> carIdPart : carIdPartioned)
    es.submit(new ProcessCarInThread(carIdPart,carRepo));
    
    }
    
    //Each Call Creates a new connection to JDBC 
    //Takes time to prepare Statement ( as given in hibernate statics )
    class ProcessCarInThread implements Runnable
    {
    List<String> carIds;
    CarRepository carRepo;
    public ProcessCarInThread(List<String> carIds, CarRepository carRepo )
    {
    this.carIds=carIds;
    this.carRepo=carRepo;
    }
           @Override
        public void run() {
    //query 1
    List<CarP> cars=carRepo.findCarProjections(carIds);
    //query 2
    List<SomeotherEntity> cars=otherRepo.findSomethingElse(params);
    //even query 1 and query2 is not executing in a single JDBC connection
    //Do Something
    }
    
    }
    

    我想提高性能,欢迎任何建议。

    有什么方法可以避免 JDBC 查询准备时间或 JDBC 连接获取时间吗?

    最佳答案

    非常令人惊讶的是,我当前的应用程序在 PROD 部署后也遇到了类似的性能问题。幸运的是我们能够修复它。

    根本原因:我们观察到在 @Query 中使用多个输入参数会导致性能问题。

    @Query(SELECT u.carName as carName, u.carId as carId from Car u where u.carId in (:carIds))
    

    解决方案:使用entityManager动态地形成类似的查询,并且观察到性能显着提高

    关于java - 如何在单个 JDBC 连接中执行多个 JPA 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58546947/

    相关文章:

    hibernate - 在Hibernate 5中替换SchemaExport(Configuration)

    java - SLF4J Log4J Jboss 4.3 和 EJB 3.0

    java - 不支持 ISO 3166 国家 ES?

    java - 无法启动 HBase shell

    java - 无法使用 Hibernate 连接到 Informix

    java - 关于 hibernate 中的数据检索

    spring-boot - 无法在单元测试中 Autowiring 存储库(多模块 Maven 项目)

    java - spring boot web绑定(bind)时如何拦截错误信息?

    java - 如何使用dylib文件?

    java - Spring Boot Controller 不响应 POST 请求