gpt4 book ai didi

java - JPA : EntityManager is taking too long to save the data

转载 作者:行者123 更新时间:2023-11-30 02:38:55 24 4
gpt4 key购买 nike

我有一个 csv 数据文件,总共有 100 000 条记录。我正在迭代记录并尝试为每条记录更新 5 个表。这是示例数据:

EAN Code,Site,Genric Material,Material,Sap Ean Code,Style,Color,Size,MRP,Gender,EAN Code,Season,Collection,BRAND,Color revision,Category (L5),Category (L6)
123456789,6001,000000000061000102,000000061000102001,61000102001,03/BE100,SC/TG,L/112 cm,850.00,MENS,123456789,AW12,Colors,XXXXXX,RD/TG,Tee Shirt,Graphic

每次迭代将更新的五个表如下:

  1. 大师
  2. 主描述
  3. 属性
  4. 属性值
  5. 关联表

上述各表之间的关系如下:

掌握 M-M 属性值

Master M-1 Matser描述

掌握M-M属性

属性 1-M 属性值

下面是我必须使用批处理技术在单个 session 中将 CSV 数据保存到 5 个表中的代码:

服务等级

@Service
public class EanService{

@AutoWired
public EanRepository eanrepository;

// Method that saves data from CSV to DataBase
@Transactional
public void saveEANMasterData1(BufferedReader br, String userName,
List<EanAttributes> attributes, String eanMasterName,String description) {
int i =1;

EanMasterDiscription eanDes = new EanMasterDiscription();
User user = userRepository.findUserByUsername(userName);
EanMasterDiscription deciption = null;
eanDes.setDescription(description);
eanDes.setMasterName(eanMasterName);
eanDes.setDate(new Timestamp(Calendar.getInstance()
.getTimeInMillis()));
String line;
try {
List<Ean> eans = new ArrayList<Ean>();
// iterating over each record in the CSV and saving the data into DB
while (((line = br.readLine()) != null)) {
String[] cols = line.split(",");
// Style Keeping Unit
Ean ean = new Ean();
for(EanAttributes attr : attributes){
EanAttributeValues eanAttributeValues = new EanAttributeValues();
if(attr.getAttrInferredType().equalsIgnoreCase("EAN")){
ean.setEAN(cols[attr.getAttributeOrder()]);
}else if(attr.getAttrInferredType().equalsIgnoreCase("Season")){
ean.setSeason(cols[attr.getAttributeOrder()]);
}else {
if(attr.getAttrInferredType().equalsIgnoreCase("Attribute")){
EanAttributes eanAttr = eanrepository.loadAttrsListByAttName(attr.getAttributeName());
if(eanAttr == null){
eanAttributeValues.setAttributeValue(cols[attr.getAttributeOrder()]);
eanAttributeValues.setEanAttributes(attr);
ean.getEanAttributeValues().add(eanAttributeValues);
ean.getEanAttributes().add(attr);
attr.getEan().add(ean);
}else{
ean.getEanAttributes().add(eanAttr);
eanAttr.getEan().add(ean);
if(eanrepository.isAttributeValueAvailable(cols[attr.getAttributeOrder()])){
eanAttributeValues.setAttributeValue(cols[attr.getAttributeOrder()]);
eanAttributeValues.setEanAttributes(eanAttr);
ean.getEanAttributeValues().add(eanAttributeValues);
}else{
EanAttributeValues values = eanrepository.loadDataByAttrValue(cols[attr.getAttributeOrder()]);
ean.getEanAttributeValues().add(values);
values.getEan().add(ean);
}
}
eanAttributeValues.getEan().add(ean);
}
}
}
if(!eanrepository.isEanMasterNameAvailable(eanMasterName)){
EanMasterDiscription eanMasterDes = eanrepository.loadDataByMasterName(eanMasterName);
ean.setEanMasterDesciption(eanMasterDes);
}else{
ean.setEanMasterDesciption(eanDes);
}
ean.setUser(user);
if(eanrepository.isEanWithSeasonAvailable(ean.getEAN(),ean.getSeason())){
// Persisting Ean; I think there is some problem with this method
eanrepository.saveEanData(ean,i);
}else{
System.out.println("************ EAN ALREADY EXIST ******************** ");
}

i++;
}
} catch (NumberFormatException | IOException e) {
e.printStackTrace();
}
}
}

存储库类

@Repository
public class EanRepository{

@PersistanceContext
EntityManager em;

public void saveEanData(Ean ean , int recordNum){
em.merge(ean);
if(recordNum % 50 == 0){
em.flush();
em.clear();
// em.getEntityManagerFactory().getCache().evictAll();
}
}

}

但这需要太多时间(近 10 小时)才能完成保存所有 100 000 条记录。我们怎样才能减少时间和我错过的东西?

最佳答案

我在批处理应用程序中遇到了同样的问题,我们采用了两种技术,大大加快了导入数据的过程:

1) 多线程 - 您必须利用多线程处理文件数据并进行保存。

我们的方法是首先从文件中读取所有数据并将其打包到一组 POJO 对象中。

然后根据我们可以创建的可能线程的数量,我们将均匀地分割集合并为线程提供一定范围的数据。

然后每组将被并行处理。

我不会深入讨论细节,因为这超出了这个问题的范围。我可以给出的一个提示是,您应该尝试利用 java.util.concurrent 及其提供的功能。

2) 批量保存 - 我们所做的第二个改进是利用 hibernate 的批量保存功能(您已经添加了 Hibernate 标签,所以我假设这是您的底层持久性提供程序):

您可以尝试利用批量插入功能。

您可以定义 hibernate 属性来启用此功能:

<property name="jdbc.batch_size">250</property>

使用此批处理设置,您应该得到如下输出:

insert into Table(id , name) values (1, 'na1') , (2, 'na2') ,(3, 'na3')..

而不是

insert into Table(id , name) values (1, 'na1');
insert into Table(id , name) values (2, 'na2');
insert into Table(id , name) values (3, 'na3');

3) 刷新计数 - 在刷新到数据库之前,您将计数设置为 50.. 现在启用了批量插入,也许您可​​以将其提高一点到几个 houndread.. 尝试尝试这个数字来找到最佳点。

关于java - JPA : EntityManager is taking too long to save the data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42325166/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com