Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring Boot JPA存储时的存储性能()_Java_Spring_Hibernate_Spring Boot_Spring Data Jpa - Fatal编程技术网

Java Spring Boot JPA存储时的存储性能()

Java Spring Boot JPA存储时的存储性能(),java,spring,hibernate,spring-boot,spring-data-jpa,Java,Spring,Hibernate,Spring Boot,Spring Data Jpa,我的spring boot应用程序在插入数据时性能非常慢 我正在从一个数据库中提取一大部分数据,并将数据插入另一个数据库 以下是我的实体 @Entity @Table(name = "element") public class VXMLElementHistorical { @Id @Column(name = "elementid") private long elementid; @Column(name = "elementname") private String eleme

我的spring boot应用程序在插入数据时性能非常慢

我正在从一个数据库中提取一大部分数据,并将数据插入另一个数据库

以下是我的实体

@Entity
@Table(name = "element")
public class VXMLElementHistorical {

@Id
@Column(name = "elementid")   
private long elementid;

@Column(name = "elementname")
private String elementname; 

Getter/Setter methods...    
我已经配置了一个JPA存储库

public interface ElementRepository extends JpaRepository<Element, Long> {

}
public interface ElementRepository扩展了JpaRepository{
}
并使用我的对象调用save()方法

@Transactional 
public void processData(List<sElement> hostElements) 
throws DataAccessException { 

List<Element> elements = new ArrayList<Element>();    

for (int i = 0; i < hostElements.size(); i++) {
        Element element = new Element();
        element.setElementid(hostElements.get(i).getElementid());
        element.setElementname(hostElements.get(i).getElementname());
        elements.add(element);
    }

   try{
   elementRepository.save(elements);{
   //catch etc...

}
@Transactional
public void processData(列出宿主元素)
抛出DataAccessException{
列表元素=新的ArrayList();
对于(int i=0;i
发生的情况是,对于每个项目,执行插入需要6到12秒。我已打开hibernate跟踪日志记录和统计,当我调用save函数时,hibernate执行两个查询,一个选择和一个插入。选择查询占用了99%的总时间

我直接在数据库上运行了select查询,结果以纳秒的速度返回。这让我相信这不是索引问题,但我不是DBA

我已经在我的dev环境中创建了一个负载测试,并且使用类似的负载大小,整个过程的时间没有prod环境中的时间长


有什么建议吗?

正如@M.Deinum在评论中所说的那样,您可以通过在一定数量的插入后调用
flush()
clear()
进行改进,如下所示

int i = 0;
for(Element element: elements) {
    dao.save(element);
    if(++i % 20 == 0) {
        dao.flushAndClear();
    }

}

不要创建元素列表并保存这些元素,而是保存单个元素。每隔一段时间进行
刷新
清除
,以防止脏检查成为瓶颈

@PersistenceContext
private EntityManager entityManager;

@Transactional 
public void processData(List<sElement> hostElements) 
throws DataAccessException {     

for (int i = 0; i < hostElements.size(); i++) {
        Element element = new Element();
        element.setElementid(hostElements.get(i).getElementid());
        element.setElementname(hostElements.get(i).getElementname());
        elementRepository.save(element)
        if ( (i % 50) == 0) {
            entityManager.flush();
            entityManager.clear();
        }
}
entityManager.flush(); // flush the last records.
如果您的JDBC驱动程序支持,这将把50个单insert语句转换为1个大批量insert,即50个insert转换为1个insert


另请参见

,因为加载实体似乎是一个瓶颈,您只需要执行插入操作,即您知道数据库中不存在实体,因此可能不应该使用Spring Data JPA的标准
保存
方法

原因是它执行了一个
合并
,这会触发Hibernate来加载数据库中可能已经存在的实体

相反,请向存储库中添加一个,该存储库在实体管理器上执行
持久化
。由于您事先设置了
Id
,请确保您有一个版本属性,以便Hibernate可以确定这确实是一个新实体

这将使选择消失

其他答案中给出的其他建议值得作为第二步考虑:

  • 启用批处理
  • 尝试中间冲洗和清除会话
  • 一次保存一个实例,而不将它们收集到集合中,因为调用
    merge
    persist
    实际上不会触发对数据库的写入,但只有刷新才会触发(这是一种简化,但应适用于此上下文)

我们在项目中使用spring数据jpa,插入元素从未花过这么长时间。可能根本原因与spring数据jpa不同,首先你不应该转换,将其放在列表中,然后保存所有元素。你已经有效地复制了所有元素(这将增加内存)。此外,您在一个大型事务中执行所有操作,这也会导致问题。相反,请直接保存创建的元素,并对每个x元素(例如50个)执行
刷新
清除
。最好您还将刷新模式设置为手动(以防止在其间进行脏检查和刷新)。由于大部分时间用于加载数据,因此清除缓存实际上可能会降低性能。
spring.jpa.properties.hibernate.jdbc.batch_size=50