如何提高速度-----从数据库查询出3万条数据,并对每条数据进行处理后,生成5M文件

时间:2021-05-08 23:20:39
从数据库查询出3万条数据,并对每条数据进行处理后,生成5M文件。
以下代码生成文件需要3分钟。
我想请教各位老师,如何能提高速度最好能1分钟以内,我不知道该怎么改这块代码,请指教

代码如下



private int genFile(String fileName, ResultSet rs) throws DaoException {
File file = null;
FileWriter writer = null;
int count = 0;
int max = 65535;
ResultSetMetaData rm = null;

int size = max;
try {
             
file = new File("c://" + fileName);
if (file.exists()) {
Validate.isTrue(file.delete(),"文件删除失败");                        
}
if (!file.createNewFile()) {
throw new DaoException("创建文件失败!");
}
writer = new FileWriter(file);

writer.write(("查询结果" + "\n"));

rm = rs.getMetaData();

while (rs.next()) {
for (int i = 1; i <= rm.getColumnCount(); i++) {
writer.write(filter(rs.getString(i)));
writer.write('|');
}
writer.write('\n');
if ((++count) == max || count > 50000) {
break;
}
}
writer.flush();
if (count < max)
size = count;

} catch (Exception e) {
logger.error(e.getMessage(), e);
throw new DaoException("生成文件失败!" + e.getMessage());
} finally {
try {
if (writer != null)
writer.close();
} catch (Exception e) {
}
}
return count;
}


13 个解决方案

#1


用bufferedwriter写

#2


这个慢的原因是因为你没读取一条记录就写入文件一次,这势必增加了IO的开销,可以使用楼上推荐的带有缓冲区的writer试试

#3


引用 2 楼 sky_walker85 的回复:
这个慢的原因是因为你没读取一条记录就写入文件一次,这势必增加了IO的开销,可以使用楼上推荐的带有缓冲区的writer试试


恩,我也觉得是因为我每条都需要处理的结果

我把filewriter 改成了bufferedwriter还是很慢


BufferedWriter writer = new BufferedWriter(new FileWriter(file));

#4


引用 1 楼 huxiweng 的回复:
用bufferedwriter写


我把filewriter 改成了bufferedwriter还是很慢


BufferedWriter writer = new BufferedWriter(new FileWriter(file));

#5


引用 3 楼 lever716 的回复:
Quote: 引用 2 楼 sky_walker85 的回复:

这个慢的原因是因为你没读取一条记录就写入文件一次,这势必增加了IO的开销,可以使用楼上推荐的带有缓冲区的writer试试


恩,我也觉得是因为我每条都需要处理的结果

我把filewriter 改成了bufferedwriter还是很慢


BufferedWriter writer = new BufferedWriter(new FileWriter(file));


默认的BufferedWriter缓冲8192个字符,你可以在构造函数中指定缓存的字符数,楼书试一下吧

#6


引用 5 楼 sky_walker85 的回复:
Quote: 引用 3 楼 lever716 的回复:

Quote: 引用 2 楼 sky_walker85 的回复:

这个慢的原因是因为你没读取一条记录就写入文件一次,这势必增加了IO的开销,可以使用楼上推荐的带有缓冲区的writer试试


恩,我也觉得是因为我每条都需要处理的结果

我把filewriter 改成了bufferedwriter还是很慢


BufferedWriter writer = new BufferedWriter(new FileWriter(file));


默认的BufferedWriter缓冲8192个字符,你可以在构造函数中指定缓存的字符数,楼书试一下吧



问题不在那,我觉得,我都用nio了,我也试了在实例化的时候制定字节数,没用,

#7


虽然帮不上忙 但是顶顶 不能沉了 

#8


你先估计一下你的内存够用不,如果够,就把3万条数据全部取出来,再计算结果,再把计算出的结果一次性写入文本文本。

#9


两个问题。

1.ResultSet的每一次循环是不是会命中数据库,命中的话就有一次网络IO。是不是可以根据可以使用的内存来拿数据,比如一次性拿出100条,然后下一次再拿100条直到取不足100条了表示最后一批了。

2.你每条记录都输出一次文件,如楼上所说的增加一个缓冲可以减少IO。不过如果需要更快话,你又会使用NIO的API的话试一下FileChannle.map()这个直接内存映射来写文件。

我个人觉得取数据少量时可以直接使用ResultSet,但是在有效率要求的地方最好还是自己来组织SQL完成。你知道每一次调用ResultSet.next()的时候是会一次性读取几条数据放在内存,还是只拿当前一条?

#10


为什么每rs.next()写一次,不换种思路;  就算先把3W条数据全load出来放到内存里面再写一次性写进文件也要比这种方式快!

#11


如果是数据的话可以导出到excel,每增加一条数据只是添加一行,应该会快很多

#12


我怎么觉得问题在26行:
filter(rs.getString(i)) 这个方法的问题呢?

#13


顶楼上,可能filter那里有影响;
另外,用BufferedWriter减少IO次数,这个是很重要一点;

#1


用bufferedwriter写

#2


这个慢的原因是因为你没读取一条记录就写入文件一次,这势必增加了IO的开销,可以使用楼上推荐的带有缓冲区的writer试试

#3


引用 2 楼 sky_walker85 的回复:
这个慢的原因是因为你没读取一条记录就写入文件一次,这势必增加了IO的开销,可以使用楼上推荐的带有缓冲区的writer试试


恩,我也觉得是因为我每条都需要处理的结果

我把filewriter 改成了bufferedwriter还是很慢


BufferedWriter writer = new BufferedWriter(new FileWriter(file));

#4


引用 1 楼 huxiweng 的回复:
用bufferedwriter写


我把filewriter 改成了bufferedwriter还是很慢


BufferedWriter writer = new BufferedWriter(new FileWriter(file));

#5


引用 3 楼 lever716 的回复:
Quote: 引用 2 楼 sky_walker85 的回复:

这个慢的原因是因为你没读取一条记录就写入文件一次,这势必增加了IO的开销,可以使用楼上推荐的带有缓冲区的writer试试


恩,我也觉得是因为我每条都需要处理的结果

我把filewriter 改成了bufferedwriter还是很慢


BufferedWriter writer = new BufferedWriter(new FileWriter(file));


默认的BufferedWriter缓冲8192个字符,你可以在构造函数中指定缓存的字符数,楼书试一下吧

#6


引用 5 楼 sky_walker85 的回复:
Quote: 引用 3 楼 lever716 的回复:

Quote: 引用 2 楼 sky_walker85 的回复:

这个慢的原因是因为你没读取一条记录就写入文件一次,这势必增加了IO的开销,可以使用楼上推荐的带有缓冲区的writer试试


恩,我也觉得是因为我每条都需要处理的结果

我把filewriter 改成了bufferedwriter还是很慢


BufferedWriter writer = new BufferedWriter(new FileWriter(file));


默认的BufferedWriter缓冲8192个字符,你可以在构造函数中指定缓存的字符数,楼书试一下吧



问题不在那,我觉得,我都用nio了,我也试了在实例化的时候制定字节数,没用,

#7


虽然帮不上忙 但是顶顶 不能沉了 

#8


你先估计一下你的内存够用不,如果够,就把3万条数据全部取出来,再计算结果,再把计算出的结果一次性写入文本文本。

#9


两个问题。

1.ResultSet的每一次循环是不是会命中数据库,命中的话就有一次网络IO。是不是可以根据可以使用的内存来拿数据,比如一次性拿出100条,然后下一次再拿100条直到取不足100条了表示最后一批了。

2.你每条记录都输出一次文件,如楼上所说的增加一个缓冲可以减少IO。不过如果需要更快话,你又会使用NIO的API的话试一下FileChannle.map()这个直接内存映射来写文件。

我个人觉得取数据少量时可以直接使用ResultSet,但是在有效率要求的地方最好还是自己来组织SQL完成。你知道每一次调用ResultSet.next()的时候是会一次性读取几条数据放在内存,还是只拿当前一条?

#10


为什么每rs.next()写一次,不换种思路;  就算先把3W条数据全load出来放到内存里面再写一次性写进文件也要比这种方式快!

#11


如果是数据的话可以导出到excel,每增加一条数据只是添加一行,应该会快很多

#12


我怎么觉得问题在26行:
filter(rs.getString(i)) 这个方法的问题呢?

#13


顶楼上,可能filter那里有影响;
另外,用BufferedWriter减少IO次数,这个是很重要一点;