我正在尝试从表中检索数据并将每行转换为CSV格式,如
s12,james,24,1232,Salaried
以下代码完成了这项工作,但需要很长时间,行表超过1,00,000。
请告知优化技术:
while(rset1.next()!=false) {
sr=sr+"\n";
for(int j=1;j<=rsMetaData.getColumnCount();j++)
{
if(j< 5)
{
sr=sr+rset1.getString(j).toString()+",";
}
else
sr=sr+rset1.getString(j).toString();
}
}
/ SR
答案 0 :(得分:15)
两种方法,按优先顺序排列:
流输出
PrintWriter csvOut = ... // Construct a write from an outputstream, say to a file
while (rs.next())
csvOut.println(...) // Write a single line
(请注意,您应该确保缓存您的Writer / OutputStream,尽管默认情况下有很多)
使用StringBuilder
StringBuilder sb = new StringBuilder();
while (rs.next())
sb.append(...) // Write a single line
这里的想法是在循环中附加字符串是一个坏主意。想象一下,你有一个字符串。在Java中,字符串是不可变的。这意味着要附加到字符串,您必须复制整个字符串,然后再写更多内容。由于你一次只附加一些东西,你将拥有许多字符串的副本,这些副本并不是真的有用。
如果您正在写一个文件,那么直接用流或Writer写出来是最有效的。否则,您可以使用StringBuilder,它可以更有效地将许多小字符串附加到一起。
答案 1 :(得分:5)
我不是Java专家,但我认为在条件检查中使用类似getColumnCount()的东西总是不好的做法。这是因为在每个循环之后,它运行该函数以查看列数是多少,而不是仅仅引用静态数字。相反,设置一个等于该数字的变量,并使用该变量与j进行比较。
答案 2 :(得分:1)
您可能希望使用StringBuilder来构建字符串,这在您进行大量连接时效率更高。此外,如果您拥有那么多数据,您可能需要考虑将其直接写入您要放置的位置,而不是首先在内存中构建它,例如,如果这是文件或套接字。
答案 3 :(得分:1)
StringBuilder sr = new StringBuilder();
int columnCount =rsMetaData.getColumnCount();
while (rset1.next()) {
sr.append('\n');
for (int j = 1; j <= columnCount; j++) {
sr.append(rset1.getString(j));
if (j < 5) {
sr.append(',');
}
}
}
答案 4 :(得分:1)
我认为微小的代码更改不会带来实质性的改变。我肯定会使用StringBuffer。
假设他的数据库在一台单独的机器上,他将通过电线读取一百万行。首先,如果性能是不可接受的,我会在数据库服务器上运行该代码并将网络剪切掉。如果是那种每周运行一次的代码作为批处理作业可能没问题。
现在,一旦从数据库中完全加载,你将如何处理StringBuffer或String?我们正在寻找一个长度为50 MB的字符串。
这应该快1,因为它删除了不需要的(i&lt; 5)检查。
StringBuilder sr = new StringBuilder();
int columnCount =rsMetaData.getColumnCount();
while (rset1.next()) {
for (int j = 1; j < columnCount; j++) {
sr.append(rset1.getString(j)).append(",");
}
// I suspect the 'if (j<5)' really meant, "if we aren't on the last
// column then tack on a comma." So we always tack it on above and
// write the last column and a newline now.
sr.append(rset1.getString(columnCount)).append("\n");
}
}
另一个答案是更改选择,以便返回逗号sep字符串。然后我们读取单列结果并将其附加到StringBuffer。
我现在忘记了语法,但是:
select column1 || "," || column2 || "," ... from table;
现在我们不需要循环和逗号连接业务。
StringBuilder sr = new StringBuilder();
while (rset1.next()) {
sr.append(rset1.getString(1)).append("\n");
}
}
答案 5 :(得分:1)
作为完全不同的,但无疑是最佳替代方案,使用DB提供的导出工具。目前还不清楚您使用的是哪个数据库,但根据您的question history,您似乎对Oracle做了很多工作。在这种情况下,您可以使用UTL_FILE
将表格导出为CSV文件。
答案 6 :(得分:1)
正如其他答案所说,停止附加到字符串。在Java中,String对象是不可变的,因此每个append必须执行字符串的完整副本,将其转换为O(n ^ 2)操作。
另一个是大减速是获取大小。默认情况下,驱动程序可能一次获取一行。即使这需要1毫秒,这也会限制你每秒一千行。即使在同一网络上,远程数据库也会更糟糕。尝试在Statement上调用setFetchSize(1000)。请注意,将提取大小设置得太大会导致某些数据库驱动程序出现内存不足错误。