Java导出数据库查询结果为excel和csv的对比

1.背景

       最近在应对一个数据查询导出模块,总体要求就是依据给定的SQL语句,输出其查询结果为csv或者xlsx文件。其中查询数据量可能会有大数据量,成百上千万都可能。

2.探讨

       针对上述数据导出这个问题,提取出几个关键词:

  • 1、SQL是由作业人员临时写的。
  • 2、数据量大。
  • 3、输出csv或xlsx文件。

       针对这几个关键词,咱分别扩展下其含义:

       第一个关键词:SQL是临时写的,这就意味着咱只是去执行这条语句,并不能对语句进行分页设计啥的,如果要重新分析SQL可能比较困难。这个时候比较贴近的场景就是“数据库查询客户端”,客户端只管执行SQL,至于执行得快慢等取决于语句及数据库性能等。

       第二个关键词:数据量大,即查询的返回结果可能比较多,你如何处理返回结果,是将其先存到List列表还是直接在结果集里面就给输出到文件。这就需要考虑内存、机器性能问题,不要一条语句执行了,直接导致你的java程序死掉了,比如JVM内存溢出,CPU使用率蹭蹭的涨到99%,导致整个程序无响应。

       第三个关键词:输出csv或xlsx文件,比如csv是利用成熟的三方库还是自己写(毕竟就是逗号分隔的文本),不同人可能有不同看法,但是我主张大家用现成的三方依赖包,比如javacsv\opencsv都是比较成熟的工具包。

       其中,有关csv读写在文章《 利用JavaCSV API来读写csv文件》中有详细介绍。而有关xlsx读写需要的jar包则在前面的文章《 Java处理excel两种不同的方式》有过介绍。

3.实现

       在实例“Java导出数据库查询结果”中,我选取的实现方法为直接在ResultSet结果集中将数据写入到文件,这么操作基于两点:

  • 1、做分页困难,没法降低查询数据量。
  • 2、大数据量内存稀缺,尽量减少重复数据存储。

在导出xlsx里面需要补充说明一点的就是SXSSFWorkbook这个对象的使用,如下:

Workbook wb = new SXSSFWorkbook(500);

因为通常咱使用习惯都是利用XSSFWorkbook来创建xlsx,两者明显的区别就是,SXSSFWorkbook可以设定内存数据写入硬盘的阈值,即每提交多少条数据就写入一次硬盘,有效的避免了大数据量存储时内存溢出的风险。比如代码中我指定的阈值为500条。

SXSSF是对XSSF的扩展,用来应对大容量电子表格的输出,自3.8-beta3版本的poi库就添加了


excel存储容量,2010版后支持单张sheet表格最大行数1048576,sheet表最大数目没有统一说法,但有一点可以肯定,数据量大太加上自己电脑的性能的限制,excel整体性能会受影响,不是说无限制往里存。


csv与excel数据存储能力及效率对比:

属性 csv excel
存储容量 没有限制,类似txt文本 单张sheet表有限制,可以存大量sheet表
存储效率 相对csv慢
占用空间 相同内容,少量时占用空间少,大量时占用空间大 相同内容,少量占用空间大,大量占用空间少

   其中相同文件名均代表同一SQL输出不同格式的文件,从下图中可以看出,相同的查询结果,如果内容较少(几十KB),存放在csv文件中占用空间较少。如果内容较大(几百KB),存放在excel文件中占用空间较少,这个应该是excel文件在大容量时做了性能优化。毕竟MicroSoft是靠系统和办公软件起家,其excel还是具备含金量的,不仅仅是好看,在高级层面还是做了不少工作的。

       输出csv及excel文件结果对比图:

Java导出数据库查询结果为excel和csv的对比