简单记录一下导出几百万数据的过程,
导出的话可以,但是你要一次性查出百万数据估计肯定会内存溢出,所以处理查询的需要自己去写
我们的业务需求是,
要求查出一年的设备报警数据,一年大概是20-30亿条数据
所以我经过多次实验,感觉按月查比较快,筛选出一个月内达到要求的报警数据,差不多一次筛选出五六万条
用时10分钟左右。筛选出以后调用下面的方法。由于我筛选以后数据量并不大,最大的差不多也在20万一下,所以我
用一个sheet存一万条数据,当然也可以存十万。百万最好不好存,会卡。
核心工具类,用于导出数据的处理
new SXSSFWorkbook(1000); //大于1000行时会把之前的行写入硬盘,解决内存溢出
private static Integer count = 0;//计数,看是否满足创建一个sheet的条件,因为一个sheet只能 存100万条
private static Integer countRow = 0;
/**
* 导出excel
* @param list 数据列表 List<E> 实体类列表
* @param headers 列标题,以英文逗号分割,必传
* @param includes 属性,以英文逗号分割,必传
* @param filePath 导出文件全路径
* @param sheetName sheet名称:sheet1
* @param dataPattern 日期格式:yyyy-MM-dd HH:mm:ss
* @throws Exception 另一个程序正在使用此文件,进程无法访问
*/
public static <E> void exportListEntity(List<E> list, String headers, String includes, String filePath, String sheetName, String dataPattern) throws Exception{
count = 0;
//工作簿
Workbook wb;
// 创建模板工作表
if (filePath.endsWith(".xls")) {
wb = new HSSFWorkbook();
} else {
//templatewb = new XSSFWorkbook(new FileInputStream(filePath));
//wb = new XSSFWorkbook();
wb = new SXSSFWorkbook(1000); //大于1000行时会把之前的行写入硬盘,解决内存溢出
}
String[] headerArr = headers.split(",");
String[] sheetNames = sheetName.split(",");
//String[] includeArr = includes.split(",");
//List<String> includeList = Arrays.asList(includeArr);;
//字体
Font font = wb.createFont();
//font.setFontHeightInPoints((short)14);
//font.setColor(IndexedColors.DARK_BLUE.getIndex());
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
//样式
CellStyle styleBOLD = createBorderedStyle(wb);
styleBOLD.setFont(font);
styleBOLD.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
styleBOLD.setWrapText(false); //自动换行
//样式
CellStyle styleWrap = createBorderedStyle(wb);
styleWrap.setWrapText(false);
styleWrap.setVerticalAlignment(CellStyle.VERTICAL_TOP);
System.out.println("开始:"+new Date());
Sheet sheet;
for (int q = 0,num = sheetNames.length;q<num;q++){//循环sheet
//表
sheet = wb.createSheet(sheetNames[q]);
//列宽
//sheet.autoSizeColumn(( short ) 0 ); // 调整第一列宽度
//sheet.SetColumnWidth(1, 50 * 256); //设置列宽,50个字符宽度。宽度参数为1/256,故乘以256,中文的要再乘以2
// sheet.setColumnWidth(0, 3000);
countRow = 0;
//行
Row row = sheet.createRow(0);
//单元格
Cell cell;
//写入标题行
for(int i=0; i<headerArr.length; i++){
cell = row.createCell(i);
cell.setCellValue(headerArr[i]);
cell.setCellStyle(styleBOLD);
}
//写入数据
E e; //实体类
Field[] fields; //属性数组
Field field; //属性
Object value; //属性值
DateFormat dtf = new SimpleDateFormat(dataPattern); //yyyy-MM-dd HH:mm:ss
rows:for(int i=count; i<list.size(); i++){
row = sheet.createRow(countRow+1);
countRow++;
e = list.get(i);
// 利用反射,获取属性数组
fields = e.getClass().getDeclaredFields();
for(int f=0,c=0; f<fields.length; f++){
field = fields[f];
//System.out.println(field.getName());
if(includes.contains(field.getName())){
cell = row.createCell(c);
cell.setCellStyle(styleWrap);
//cell.setCellType(Cell.CELL_TYPE_STRING);
//field.getName();
//field.getType();
field.setAccessible(true); //设置些属性是可以访问的
value = field.get(e); //得到此属性的值
//Byte,Short,Int,Long,Float,Double,Boolean,Char, String,Date,BigDecimal,byte[]
//cell.setCellValue: boolean,Calendar,Date,double,RichTextString,String
if(value==null){
} else if (value instanceof Date){
cell.setCellValue(dtf.format((Date)value));
} else {
cell.setCellValue(value.toString());
}
c++;
}
}
count++;
//当满一万条数据新建一个sheet
if(count%10000==0){
break rows;
}
}
}
//写入文件
FileOutputStream fOut = new FileOutputStream(filePath);
wb.write(fOut);
//fOut.close();
System.out.println("结束:"+new Date());
}
方法的调用
public static void main(String[] args){
List<outentity> outentities = new ArrayList<>();
outentity outentity = new outentity();
outentity.setId(1);
outentity.setPassword("123");
outentity.setUsername("123");
outentity outentity2 = new outentity();
outentity2.setId(2);
outentity2.setPassword("123");
outentity2.setUsername("123");
outentity outentity3 = new outentity();
outentity3.setId(3);
outentity3.setPassword("123");
outentity3.setUsername("123");
outentity outentity4 = new outentity();
outentity4.setId(4);
outentity4.setPassword("123");
outentity4.setUsername("123");
outentity outentity5 = new outentity();
outentity5.setId(5);
outentity5.setPassword("123");
outentity5.setUsername("123");
outentity outentity6 = new outentity();
outentity6.setId(6);
outentity6.setPassword("123");
outentity6.setUsername("123");
outentities.add(outentity);
outentities.add(outentity2);
outentities.add(outentity3);
outentities.add(outentity4);
outentities.add(outentity5);
outentities.add(outentity6);
String ll = "private int com.poi.out.poiout.entity.outentity.id,private java.lang.String com.poi.out.poiout.entity.outentity.username,private java.lang.String com.poi.out.poiout.entity.outentity.password";
try {
exportListEntity(outentities,"id,username,password",ll,"D:\\excellogs\\test.xlsx","sheet1,sheet2,sheet3","yyyy-MM-dd HH:mm:ss");
} catch (Exception e) {
e.printStackTrace();
}
}
实体类
public class outentity {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
有不足的地方还请大佬告知。