当前位置: 首页 > 后端技术 > Java

将Excel海量数据导入mongodb

时间:2023-04-02 00:10:13 Java

我需要导入Excel数据进行系统查询(近30万行)。这个Excel是全量的数据,不是增量的,是在系统外维护的。如果有变化,定期导入更新Excel导入试试普通的poi导入excel的方式,数据量太大,很容易OOMWorkbookFactory.create(file.getInputStream());我的excel只有30M左右,程序占用内存3g,还是OOM参考这个问题:https://stackoverflow.com/que...使用这个库,支持流式读取excel:https://github.com/monitorjbl...依赖参考仓库后出现MethodNotFound异常,可能是Dependency冲突,我主动排除了com.monitorjblxlsx-streamer2.1.0org.apache.poipoiorg.apache.poipoi4.1.2使用xlsx-streamer读取excel:try(InputStreamis=file.getInputStream();Workbookwb=StreamingReader.builder()//保留在内存中的行数(默认为10).rowCacheSize(100)//将InputStream读取到文件时使用的缓冲区大小(默认为1024).bufferSize(4096)//XLSX文件的InputStream或File(必需).open(is);){...…}导入mongodb的数据量比较大。如果组装java对象,肯定会浪费性能。我选择直接使用org.bson.Document来组装数据。如果使用spring-data-mongdbAPI,肯定有损失。我选择使用mongdb自带的API。:com.mongodb.client.MongoCollectionvoidinsertMany(Listvar1)批量导入。维护一个列表,从excel中读取和组合行,每1000行insertMany。这里我是全量导入,不考虑重复更新,直接新建一个集合B,导入成功后,drop旧的集合A,将集合B重命名为A,省心省力。完整代码://生成一个不会重复的表名StringcollectionName="invoiceInfo_"+newSimpleDateFormat("yyyyMMddHHmmss").format(newDate());如果(mongoTemplate.collectionExists(collectionName)){mongoTemplate.dropCollection(collectionName);}//创建表MongoCollectioncollection=mongoTemplate.createCollection(collectionName);try(InputStreamis=file.getInputStream();Workbookwb=StreamingReader.builder()//要保存在内存中的行数(默认为10).rowCacheSize(100)//将InputStream读取到文件时使用的缓冲区大小(默认为1024).bufferSize(4096)//InputStreamorFileforXLSXfile(required).open(is);){Sheetsheet=wb.getSheetAt(0);长启动=System.currentTimeMillis();List文档=newArrayList<>();诠释我=0;for(Rowrow:sheet){if(i++==0||row==null){继续;}//从第2行开始取数据,默认第1行是表头。intcol=0;文件文件=新文件();对象invoiceCode=ExcelUtil.getCellValue(row,col++);如果(StringUtils.isEmpty(invoiceCode.toString())){中断;}document.put("invoiceCode",invoiceCode);document.put("invoiceNumber",ExcelUtil.getCellValue(row,col++));document.put("billingDate",ExcelUtil.getCellValue(row,col++));document.put("buyerName",ExcelUtil.getCellValue(row,col++));document.put("buyerTaxId",ExcelUtil.getCellValue(row,col++));document.put("sellerName",ExcelUtil.getCellValue(行,列++));document.put("sellerTaxPayerId",ExcelUtil.getCellValue(row,col++));document.put("noTaxAmount",ExcelUtil.getCellValue(row,col++));document.put("taxRate",ExcelUtil.getCellValue(row,col++));document.put("taxAmount",ExcelUtil.getCellValue(row,col++));document.put("金额",ExcelUtil.getCellValue(row,col++));document.put("备注",ExcelUtil.getCellValue(row,col++));文档.add(文档);如果(i%1000==0){collection.insertMany(文档);log.info("已导入{}条",i);文档.clear();}}if(!documents.isEmpty()){collection.insertMany(documents);log.info("已导入{}条",i);}log.info("time={}",System.currentTimeMillis()-开始);//删除旧表if(mongoTemplate.collectionExists(TABLE_NAME)){mongoTemplate.dropCollection(TABLE_NAME);}//重命名新表collection.renameCollection(newMongoNamespace(mongoTemplate.getDb().getName(),TABLE_NAME));}catch(Throwablee){log.error("导入发票信息异常",e);mongoTemplate.dropCollection(collectionName);}导入结果我用的jvm配置-Xms512m-Xmx1024m限制最大内存使用1g实测30w数据导入耗时20~25秒左右,多提供内存,多花点时间,百万数据应该没问题