Java StringBuilder和ResultSet性能问题的可能原因是什么
我在Java中循环浏览一个结果集;出于测试目的,它返回大约30行,每行17列(所有字符串数据)。我正在使用StringBuilder从结果中手动构建一个XML字符串,循环完成这些迭代大约需要36秒 注意:我意识到这不是从数据库中获取XML的最佳方式,甚至不是从ResultSet中获取XML的最佳方式——但这让我好奇的是,不管怎样,性能都很慢 更新:根据到目前为止的回复,我必须解决以下问题: 运行查询的时间不到一秒钟,我在代码的每个部分之前和之后都执行了System.currentTimeMillis()来缩小范围。36秒完全在下面的代码范围内Java StringBuilder和ResultSet性能问题的可能原因是什么,java,xml,performance,jdbc,stringbuilder,Java,Xml,Performance,Jdbc,Stringbuilder,我在Java中循环浏览一个结果集;出于测试目的,它返回大约30行,每行17列(所有字符串数据)。我正在使用StringBuilder从结果中手动构建一个XML字符串,循环完成这些迭代大约需要36秒 注意:我意识到这不是从数据库中获取XML的最佳方式,甚至不是从ResultSet中获取XML的最佳方式——但这让我好奇的是,不管怎样,性能都很慢 更新:根据到目前为止的回复,我必须解决以下问题: 运行查询的时间不到一秒钟,我在代码的每个部分之前和之后都执行了System.currentTimeMill
ResultSetMetaData rsmeta = rset.getMetaData();
StringBuilder resultBuilder = new StringBuilder();
resultBuilder.append("<?xml version=\"1.0\" ?><ROWSET>");
if(numColumns != 0){
while (rset.next()) {
resultBuilder.append("<ROW>");
for (int i = 0; i <= numColumns -1;i++) {
columnName = rsmeta.getColumnName(i+1);
resultBuilder.append("<");
resultBuilder.append(columnName);
resultBuilder.append(">");
resultBuilder.append(rset.getString(i+1));
resultBuilder.append("</");
resultBuilder.append(columnName);
resultBuilder.append(">");
}
resultBuilder.append("</ROW>");
numRows += 1;
}
}
else {
stmt.close();
wsConn.close();
return "No Results";
}
ResultSetMetaData rsmeta=rset.getMetaData();
StringBuilder resultBuilder=新建StringBuilder();
resultBuilder.append(“”);
如果(numColumns!=0){
while(rset.next()){
resultBuilder.append(“”);
对于(inti=0;i我认为你的笔记2本身就说明了问题
时间不会在StringBuilder中丢失,而是在其他地方
读取元数据可能非常慢,具体取决于实现。
对于所有结果集,您只能读取它们一次,并在循环中重用它们
更新
从您上次的更新来看,StringBuilder已不受关注,问题出在结果集上。我觉得问题标题和给出的所有答案与您当前的关注点不一致。
我建议结束这个问题,为新的关注点打开一个新的问题:-)与从数据库访问和检索数据所花费的时间相比,我强烈怀疑StringBuilder是否是您的瓶颈。优化简单字符串连接并没有显著改变运行时间的事实证实了这一点
您需要优化访问数据库的方式——更快地连接到数据库,压缩连接,等等
但是,我可以为您的代码提供一个微观优化:我同意StringBuilder可能不是实时接收器,而不是添加单个字符串,如“。但是,StringBuffer可能会受到一些限制,因为它最终不得不随着缓冲区的增长(并超过其默认大小)分配额外的空间.这个建议解决了你的问题,但我还是怀疑他们能否解决你的问题
祝你好运尝试用罐装数据替换各种呼叫。例如,有人认为访问元数据是罪魁祸首。尝试替换:
columnName = rsmeta.getColumnName(i+1);
与:
其中i是在循环之前设置为0并在循环中递增的整数。实际使用getColumnName()、next()和getValue()从结果集中读取信息通常比首先获取结果花费的时间要多得多。对于不可滚动的结果集尤其如此
StringBuilder以指数方式分配内存(newSize=FACTOR*oldSize),因此执行的操作越多,需要重新分配的内存就越少
要真正测试这一点,只需将rset和rsmeta替换为具有相同方法的虚拟对象:let next()对于实际数量的行,返回true,并让其他方法返回实际长度的字符串。我非常怀疑StringBuilder
是否是罪魁祸首。Java广泛使用它,我也广泛使用它,我为我自己的JVM重写了它,基本上它总是能够吃掉数百m的字符百万每秒
我认为您的问题来自数据库访问本身。当您运行查询并获得ResultSet
时,并不一定意味着所有数据都已获得并在内部转换为易于管理的内存表示形式。这取决于数据库实现(及其JDBC驱动程序),当调用ResultSet.next()
和ResultSet.getString()
方法时,可以动态获取大量结果
尝试简单地探索结果,调用所有的next()
和getString()
,但不将获得的数据存储在StringBuilder
中。如果仍然需要36秒,那么StringBuilder
是无辜的(我坚信这一点).问题是,结果集
有一个到数据库的持久链接,在调用时可以获取更多信息。我建议您查看缓存集
(javadoc)。它将立即下拉所有数据,并与结果集
完全相同。然后,您可以关闭数据库连接,然后开始解析数据。我建议您尝试一下,看看它是否加快了您的处理过程。检查您是如何返回结果集的。语句中有一些方法允许您更改ResultSet拉入数据的方式
特别是看
我昨天遇到了类似的问题:在Microsoft SQL server 10中查询大约170万条记录并读取值大约需要50分钟。更改后,大约需要80秒
我的问题是使用的jdbc驱动程序:唯一的更改是从com.microsoft.sqlserver.jdbc 1.2版驱动程序更改为net.sourceforge.jtds 1.2.2版驱动程序…我很确定您这里的问题不是StringBuilder
。尝试删除所有提到的StringBuilder
,只保留循环和getColumnName()
和getString()
调用。您正在对数据库连接进行性能测试。如何确定瓶颈不是数据库?更新时:查询只是数据库操作的第一部分。结果集通常是数据库游标的外观。这就是
while (numRows <= 160) {
// same as above
}
columnName = rsmeta.getColumnName(i+1);
columnName = rsmeta.getColumnName(i+1);
columnName = "Column" + i;