我有一个方法,它将44 MB的数据从一个ResultSet写入一个CSV文件。然而,它大约需要3.5分钟才能完成。对于44 MB的数据来说,这似乎很慢。有人能看到任何东西减慢我的代码吗?:
public static void convertToCSV(final ResultSet rs) throws SQLException, IOException {
final BufferedWriter fw = new BufferedWriter(new FileWriter(new File("alert.csv")));
while (rs.next()) {
fw.write(rs.getString("FIELD1")+",");
fw.write(rs.getString("FIELD2")+",");
fw.write(rs.getString("FIELD3")+",");
final String clobValue = rs.getString("FIELD4");
if(clobValue==null)
fw.write("null,");
else{
fw.write("\""+clobValue+"\",");
}
final Date date = new Date(rs.getLong("FIELD5"));
final DateFormat format = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
final String dateTime[] = format.format(date).split(" ");
fw.write(dateTime[0]+",");
fw.write(dateTime[1]);
fw.write("\n");
}
fw.close();
}发布于 2015-10-20 14:12:30
像这样的东西可能会更快
public static void convertToCSV(final ResultSet rs) throws SQLException, IOException {
final BufferedWriter fw = new BufferedWriter(new FileWriter(new File("alert.csv")));
final DateFormat format = new SimpleDateFormat("'yyyyMMdd','HH:mm:ss'");
format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
while (rs.next()) {
StringBuilder sb = new StringBuilder();
sb.append(rs.getString("FIELD1")).append(',')
.append(rs.getString("FIELD2")).append(',')
.append(rs.getString("FIELD3")).append(',');
final String clobValue = rs.getString("FIELD4");
if(clobValue==null)
sb.append("null,");
else{
sb.append('\"').append(clobValue).append('\"').append(',');
}
Date date = new Date(rs.getLong("FIELD5"));
sb.append(format.format(date)).append('\n');
fw.write(sb.toString());
}
fw.close();
}DateFormat的创建只能在循环之外完成一次。StringBuilder您甚至可以重用StringBuilder,方法是将创建移出循环,并在编写完它之后执行setLength(0)。
发布于 2015-10-20 14:03:40
这可能取决于JDBC驱动程序、获取策略、磁盘.
但是,您当然可以避免创建这么多临时对象:
DateFormat移出循环。rs.getString("FIELD1")+",",而是对编写器执行两次写调用。发布于 2015-10-20 14:13:12
您可以在生成Statement的ResultSet上增加获取大小--这将减少返回数据库获取下一批行所需的次数(默认设置为10 )。它的缺点是它将增加ResultSet的内存占用,因为它将在内存中保存更多的数据。
您的SimpleDatFormat对象是在循环的每次迭代中使用相同的数据创建的--如果将它移出循环,则只实例化它一次。您也可以将setTimeZone(...)语句移出循环之外。
每次使用变量值进行String连接时,都会在内部创建一个新的StringBuilder对象--您可以通过确保从未在循环中进行连接来获得更多的收益。您可以手动创建自己的StringBuilder,将整个行的数据值放入其中,然后将该行写入BufferedWriter一次(可能会牺牲更多的内存),也可以输入更多的write(...)调用以避免进行连接。
https://stackoverflow.com/questions/33238704
复制相似问题