Hibernate查询变得越来越慢

egdjgwm8  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(184)

我正在研究一个检查和更新Oracle数据库中数据的过程。我在我的应用程序中使用了hibernate和spring框架。
应用程序读取csv文件,处理内容,然后持久化实体:

public class Main() {
    Input input = ReadCSV(path);
    EntityList resultList = Process.process(input);
    WriteResult.write(resultList);
    ...
}

// Process class that loops over input
public class Process{
public EntityList process(Input input) :
   EntityList results = ...;
   ...
   for(Line line : input.readLine()){
     results.add(ProcessLine.process(line))
   ...
   }
   return results;
}
// retrieving and updating entities
Class ProcessLine {
@Autowired
DomaineRepository domaineRepository;
@Autowired
CompanyDomaineService companydomaineService
@Transactional
public MyEntity process(Line line){
  // getcompanyByXX is CrudRepository method with @Query that returns an entity object
  MyEntity companyToAttach = domaineRepository.getCompanyByCode(line.getCode());
  MyEntity companyToDetach = domaineRepository.getCompanyBySiret(line.getSiret());
  if(companyToDetach == null || companyToAttach == null){
     throw new CustomException("Custom Exception");
  }
  // AttachCompany retrieves some entity  relationEntity, then removes companyToDetach and adds CompanyToAttach. this updates relationEntity.company attribute.
  companydomaineService.attachCompany(companyToAttach, companyToDetach);
  return companyToAttach;
}
}

public class WriteResult{
@Autowired
DomaineRepository domaineRepository;
@Transactional
public void write(EntityList results) {
   for (MyEntity result : results){
       domaineRepository.save(result)
   }
}
}

字符串
该应用程序在行数较少的文件上运行良好,但当我尝试处理大文件(200000行)时,性能急剧下降,并且我会得到SQL超时。我怀疑缓存问题,但我想知道在处理结束时保存所有实体是否不是一个坏的做法?

cwdobuhd

cwdobuhd1#

对于你读的每一行,你在这里做了2次读操作
MyEntity companyToAttach = domaineRepository.getCompanyByCode(line.getCode()); MyEntity companyToDetach = domaineRepository.getCompanyBySiret(line.getSiret());
您可以读取多行并使用in查询,然后处理该公司列表

ybzsozfc

ybzsozfc2#

问题是for循环对结果进行单独保存,因此单个插入会减慢速度。Hibernate和Spring支持批量插入,并且应该在可能的情况下进行。
domaineRepository.saveAll(results)
由于您正在处理大量的数据,所以最好是分批处理,因此与其获取一个公司附加,您应该获取一个公司列表,以附加流程,然后获取一个公司列表,以分离和处理这些

public EntityList process(Input input) :
   EntityList results;
   List<Code> companiesToAdd = new ArrayList<>();
   List<Siret> companiesToRemove = new ArrayList<>(); 
   for(Line line : input.readLine()){
      companiesToAdd.add(line.getCode());
      companiesToRemove.add(line.getSiret());
   ...
   }
   results = process(companiesToAdd, companiesToRemove);
   return results;
}

public MyEntity process(List<Code> companiesToAdd, List<Siret> companiesToRemove) {
  List<MyEntity> attachList = domaineRepository.getCompanyByCodeIn(companiesToAdd);
  List<MyEntity> detachList = domaineRepository.getCompanyBySiretIn(companiesToRemove);
  if (attachList.isEmpty() || detachList.isEmpty()) {
    throw new CustomException("Custom Exception");
  }
  companydomaineService.attachCompany(attachList, detachList);
  return attachList;
}

字符串
上面的代码只是伪代码,为您指明正确的方向,需要找出适合您的方法。

相关问题