Spring Data JPA HIbernate 批量插入速度较慢

Posted

技术标签:

【中文标题】Spring Data JPA HIbernate 批量插入速度较慢【英文标题】:Spring Data JPA HIbernate batch insert is slower 【发布时间】:2016-05-22 07:11:51 【问题描述】:

我使用 Spring Data、Spring Boot 和 Hibernate 作为 JPA 提供程序,我想提高批量插入的性能。

我参考这个链接使用批处理:

http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch15.html

这是我的代码和用于插入批处理实验的 application.properties。

我的服务:

    @Value("$spring.jpa.properties.hibernate.jdbc.batch_size")
    private int batchSize;

    @PersistenceContext
    private EntityManager em;

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public SampleInfoJson getSampleInfoByCode(String code) 
//        SampleInfo newSampleInfo = new SampleInfo();
//        newSampleInfo.setId(5L);
//        newSampleInfo.setCode("SMP-5");
//        newSampleInfo.setSerialNumber(10L);
//        sampleInfoDao.save(newSampleInfo);
        log.info("starting... inserting...");
        for (int i = 1; i <= 5000; i++) 
            SampleInfo newSampleInfo = new SampleInfo();
//            Long id = (long)i + 4;
//            newSampleInfo.setId(id);
            newSampleInfo.setCode("SMPN-" + i);
            newSampleInfo.setSerialNumber(10L + i);
//            sampleInfoDao.save(newSampleInfo);
            em.persist(newSampleInfo);
            if(i%batchSize == 0)
                log.info("flushing...");
                em.flush();
                em.clear();
            
        

与批处理相关的部分application.properties:

spring.jpa.properties.hibernate.jdbc.batch_size=100
spring.jpa.properties.hibernate.cache.use_second_level_cache=false
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true

实体类:

@Entity
@Table(name = "sample_info")
public class SampleInfo implements Serializable

    private Long id;
    private String code;
    private Long serialNumber;

    @Id
    @GeneratedValue(
            strategy = GenerationType.SEQUENCE,
            generator = "sample_info_seq_gen"
    )
    @SequenceGenerator(
            name = "sample_info_seq_gen",
            sequenceName = "sample_info_seq",
            allocationSize = 1
    )
    @Column(name = "id")
    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    @Column(name = "code", nullable = false)
    public String getCode() 
        return code;
    

    public void setCode(String code) 
        this.code = code;
    

    @Column(name = "serial_number")
    public Long getSerialNumber() 
        return serialNumber;
    

    public void setSerialNumber(Long serialNumber) 
        this.serialNumber = serialNumber;
    

运行上述批量插入 5000 行的服务需要 30 到 35 秒才能完成,但如果注释这些行:

if(i%batchSize == 0)
    log.info("flushing...");
    em.flush();
    em.clear();

插入 5000 行仅需 5 到 7 秒,比批处理模式快。

为什么使用批处理模式会变慢?

【问题讨论】:

【参考方案1】:

那是因为 EntityManager 不会立即将数据保存在数据库中。当您调用flush() 时,数据将被持久化。当您注释这些行时,EntityManager 根据 flush-mode 参数刷新数据,直接调用 flush 您告诉 EntityManager 在数据库中执行查询。

【讨论】:

那么我得到的结果是正常的吗?使用批处理总是比不使用批处理要慢,对吧? 结果正常。当您的实体可以溢出休眠会话级缓存时需要批处理,但它必须是很多实体(十倍大,然后是您的示例)。如果您不知道实体数组的大小,您可以添加批处理,但将 batchSize 增加到 10 000 等 " EntityManager 在事务提交时刷新数据" 我认为这种说法是错误的。默认休眠刷新模式为自动,您无法确定刷新时间。如果刷新模式明确设置为 COMMIT,是的,这次你是对的。 jit,你是对的,我在最后一句话里也试着说同样的话。我会更正答案

以上是关于Spring Data JPA HIbernate 批量插入速度较慢的主要内容,如果未能解决你的问题,请参考以下文章

Spring整合Hibernate实现Spring Data JPA

Spring Data JPA 和 Hibernate

Spring-data-jpa + Hibernate 未创建预期表

简述 JPA 与 Spring Data JPA 与 Hibernate

spring-data-jpa+hibernate 各种缓存的配置演示

Spring Data JDBC / Spring Data JPA 与 Hibernate