I'm using spring boot, hibernate any MySQL for reading 100000 records from csv file and write the same to the database. I'm doing the batch insert where the data is committed at intervals equal to batch size. The data is saved properly but it takes around 3 minutes to insert all data. Is there anything I can do to improve the performance. Spring Batch is not allowed
This will separate the rows/records with missing values in cell.
private String selectTempFile(String fileName){
try {
List<CSVRecord> validList =new ArrayList<>();
List<CSVRecord> invalidList =new ArrayList<>();
Reader in = new FileReader(TEMP_LOCATION+fileName);
Iterable<CSVRecord> record = CSVFormat.EXCEL.withFirstRecordAsHeader().withAllowMissingColumnNames().withIgnoreHeaderCase().parse(in);
extractColumnHeader(record.iterator().next().toString());
for(CSVRecord r:record){
if(r.get(DATE).isEmpty() || r.get(TIMESTAMP).isEmpty() || r.get(FROM_CURRENCY).isEmpty()
||r.get(TO_CURRENCY).isEmpty() || r.get(SPREAD).isEmpty()){
invalidList.add(r);
}else{
validList.add(r);
}
}
log.info("start time :"+new Date().toString());
setInvalidDeal(invalidList,fileName);
setValidDeal(validList,fileName);
validCSVWriter(validList, fileName);
invalidCSVWriter(invalidList, fileName);
log.info("end time :"+new Date().toString());
} catch (Exception e) {
e.printStackTrace();
}
return INDEX;
}
This will set all the deals object in list and pass for saving in db
private void setValidDeal(List<CSVRecord> validList, String fileName) {
List<ValidDeal> list=new ArrayList<>();
ValidDeal deal = null;
for(CSVRecord r:validList){
deal = new ValidDeal();
try {
deal.setDate(new SimpleDateFormat(DATE_PATTERN).parse(r.get(DATE)));
} catch (ParseException e) {
e.printStackTrace();
}
//deal.setId(UUID.randomUUID().toString());
deal.setTimeStamp(r.get(TIMESTAMP));
deal.setFromCurrencyISOCode(FROM_CURRENCY);
deal.setToCurrencyISOCode(TO_CURRENCY);
deal.setFromCurrencyISOCodeAmount(r.get(FROM_CURRENCY));
deal.setToCurrencyISOCodeAmount(r.get(TO_CURRENCY));
deal.setAmount(r.get(SPREAD));
deal.setFileName(fileName+"-valid"+new Date()+CSV_SUFFIX);
list.add(deal);
}
validDealService.saveDeal(list);
}
Entity class
@Entity
public class ValidDeal {
@Id
@GeneratedValue
private Long id;
@Column(name="from_currency_iso_code")
private String fromCurrencyISOCode;
@Column(name="to_currency_iso_code")
private String toCurrencyISOCode;
@Column(name="from_currency_iso_code_amount")
private String fromCurrencyISOCodeAmount;
@Column(name="to_currency_iso_code_amount")
private String toCurrencyISOCodeAmount;
private Date date;
private String timeStamp;
private String amount;
private String fileName;
//getters and setters
}
This inserts records to Database
public void saveDeal(List<ValidDeal> validDeal) {
int batchSize=50;
int numberOfElements=validDeal.size();
/*
* This will commit at every time when the size of persist is equal to batch size but will be slow
* Measured time 3min
*/
Session session = sessionFactory.openSession();
Transaction tx;
while (numberOfElements > 0) {
numberOfElements -= batchSize;
//if @GeneratedValue is removed from entity, same record is saved in db after first commit
tx = session.beginTransaction();
for (int i = 0; i < batchSize; i++) {
session.save(validDeal.get(i));
}
tx.commit();
session.clear();
}
/*
* This will commit after all the data are persisted in db, takes less time because commit will
* happen only at the last.
*
* Measured time 15sec to 20sec for 100000 records
*/
/*
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for(int i=0;i<validDeal.size();i++){
ValidDeal deal = validDeal.get(i);
session.save(deal);
if(i%batchSize==0){ //same as batch size
session.flush(); //flush the batch of insert
session.clear(); //release memory
}
}
tx.commit();
session.close();
*/
}