Reputation: 5966
I have a method that writes 44 MB worth of data from a ResultSet to a CSV file. However, it is taking about 3.5 minutes to complete. This seems slow for only 44 MB of data. Can anyone see anything slowing down my code?:
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();
}
Upvotes: 2
Views: 1963
Reputation: 2108
You can increase the fetch size on the Statement
that produced your ResultSet
- this will reduce the amount of times that it needs to go back to the database to fetch the next batch of rows (it is set to 10 by default). The downside of this is that it will increase the memory footprint of the ResultSet
because it will be holding more data in memory.
Your SimpleDatFormat
object is created with the same data on each iteration of the loop - if you move it outside the loop you're only instantiating it once. You can also move the setTimeZone(...)
statement outside the loop too.
String
concatenation using variable values internally creates a new StringBuilder
object each time you do it - you can make further gains by ensuring that you're never doing concatenation within your loop. You can either do this by creating your own StringBuilder
manually, putting the whole row's worth of data into it, and then writing the row to the BufferedWriter
once (at the probable expense of more memory) or you can put in more write(...)
calls to avoid doing the concatenation.
Upvotes: 1
Reputation: 124526
Something like this could be faster
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
is only done once, outside the loop.StringBuilder
You could even reuse the StringBuilder
, by moving the creation out of the loop and after writing it do a setLength(0)
.
Upvotes: 3
Reputation: 109547
The following should be a bit faster.
fw.write(rs.getString("FIELD1"));
fw.write(',');
Also declare and prepare the SimpleDateFormat before the loop.
final DateFormat format = new SimpleDateFormat("yyyyMMdd','HH:mm:ss");
(Single quotes not needed here.)
without split
which is expensive.
Upvotes: 2
Reputation: 32980
This may depend on the JDBC driver, your fetch strategy, the disk...
But you can certainly avoid creating so much temporary objects:
DateFormat
out of the loop.rs.getString("FIELD1")+","
and instead do two write calls on the writer.Upvotes: 3