使用Spring Boot 2和mysql非常缓慢地激活Spring Data JPA saveAll / save方法

时间:2018-08-07 13:07:17

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

我的Spring启动应用程序正在使用Hibernate JPA将记录保存到MySQL。

{@ {1}}经过良好而快速的工作后,突然开始非常非常缓慢地工作:插入1K记录(主键是ID)大约需要10分钟。

我虽然问题在于循环调用save(),所以我改成save(),但令我惊讶的是没有什么区别,它甚至可能需要20分钟的时间 strong>保存 1139条记录

MySQL是本地的,仅由我的开发环境使用。

这是日志文件:

saveAll()

我将它们添加到属性文件中:

2018-08-07 14:44:25:335 - About to save all new 1139 cats of Oscar 
2018-08-07 15:03:47:758 - Succeded saving the cats of Oscar
2018-08-07 15:07:41:961 - Session Metrics {
    600922575 nanoseconds spent acquiring 1140 JDBC connections;
    92320112 nanoseconds spent releasing 1139 JDBC connections;
    312825484 nanoseconds spent preparing 2283 JDBC statements;
    464811479497 nanoseconds spent executing 2279 JDBC statements;
    233368433210 nanoseconds spent executing 229 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    233765441110 nanoseconds spent executing 1 flushes (flushing a total of 1139 entities and 0 collections);
    40198 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}

这是Service方法中的代码:

spring.jpa.properties.hibernate.jdbc.batch_size=5
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
spring.jpa.properties.hibernate.generate_statistics=true

1 个答案:

答案 0 :(得分:0)

批量大小不会起作用。

这是休眠文档中的重要部分: http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#batch-session-batch-insert

批量插入

当使新对象持久化时,请定期对会话使用flush()和clear()方法,以控制第一级缓存的大小。

示例3.刷新和清除会话

EntityManager entityManager = null;
EntityTransaction txn = null;
try {
    entityManager = entityManagerFactory().createEntityManager();

    txn = entityManager.getTransaction();
    txn.begin();

    int batchSize = 25;

    for ( int i = 0; i < entityCount; i++ ) {
        if ( i > 0 && i % batchSize == 0 ) {
            //flush a batch of inserts and release memory
            entityManager.flush();
            entityManager.clear();
        }

        Person Person = new Person( String.format( "Person %d", i ) );
        entityManager.persist( Person );
    }

    txn.commit();
} catch (RuntimeException e) {
    if ( txn != null && txn.isActive()) txn.rollback();
        throw e;
} finally {
    if (entityManager != null) {
        entityManager.close();
    }
}