我的查询处理时间存在重大问题:( 我认为这是因为查询正在重新编译evrytime。但我没有看到任何解决方法。 以下是代码的查询/片段:
private void readPerformance(String startTime, String endTime,
String performanceTable, String interfaceInput) throws SQLException, IOException {
String interfaceId, iDescp, iStatus = null;
String dtime, ingress, egress, newLine, append, routerId= null;
StringTokenizer st = null;
stmtD = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY);
stmtD.setFetchSize(Integer.MIN_VALUE);
BufferedReader interfaceRead = new BufferedReader(new FileReader(interfaceInput));
BufferedWriter pWrite = new BufferedWriter(new FileWriter("performanceInput.txt"));
while((newLine = interfaceRead.readLine())!= null){
st = new StringTokenizer(newLine,",");
while(st.hasMoreTokens()){
append = st.nextToken()+CSV+st.nextToken()+st.nextToken()+CSV+st.nextToken();
System.out.println(append +" ");
iStatus = st.nextToken().trim();
interfaceId = st.nextToken().trim();
append = append + CSV+iStatus+CSV+interfaceId;
System.out.println(append +" ");
pquery = " Select d.dtime,d.ifInOctets, d.ifOutOctets from "+performanceTable+"_1_60" +" AS d Where d.id = " +interfaceId
+ " AND dtime BETWEEN " +startTime+ " AND "+ endTime;
rsD = stmtD.executeQuery(pquery);
/* interface query*/
while(rsD.next()){
dtime = rsD.getString(1);
ingress= rsD.getString(2);
egress = rsD.getString(3);
pWrite.write(append + CSV + dtime+CSV+ingress+CSV+egress+NL);
}//end while
}//end while
}// end while
pWrite.close();
interfaceRead.close();
rsD.close() ;
stmtD.close();
}
我的interfaceId值不断变化。所以我把查询放在循环中导致多次重新编译查询。
有任何betetr方式吗?我可以在java中起诉存储过程吗?如果是这样的话?对它没有多少了解。
当前处理时间差不多是60分钟(:(()!!!生成的文本文件超过300 MB 请帮忙!!!
谢谢。
答案 0 :(得分:1)
您可以使用PreparedStatement和参数,这可能会避免重新编译查询。由于performanceTable
是常量,因此可以将其放入准备好的查询中。在WHERE条件中使用的其余变量被设置为参数。
在循环外部,创建一个预准备语句,而不是常规语句:
PreparedStatement stmtD = conn.prepareStatement(
"Select d.dtime,d.ifInOctets, d.ifOutOctets from "+performanceTable+"_1_60 AS d"+
" Where d.id = ? AND dtime BETWEEN ? AND ?");
然后,在循环中,设置参数:
stmtD.setInteger(1, interfaceID);
stmtD.setInteger(2, startTime);
stmtD.setInteger(3, endTime);
ResultSet rsD = stmtD.executeQuery(); // note no SQL passed in here
最好还是使用EXPLAIN
检查来自MySQL的查询计划,看看它是否也是瓶颈的一部分。此外,函数中还有相当多的诊断字符串连接。一旦查询正常,删除它也可以提高性能。
最后,请注意,即使查询速度很快,网络延迟也可能会降低速度。 JDBC提供多个查询的批量执行,以帮助减少每个语句的总体延迟。请参阅Connection上的addBatch / executeBatch。
答案 1 :(得分:1)
需要更多信息,但我可以提供一些一般性问题/建议。它可能与编译查询计划无关(这是不寻常的)
如果每个查询的时间很长,则问题是查询执行本身,而不是编译。如上所述检查索引。
如果有许多查询,则可能是造成问题的大量查询。使用PreparedStatement(请参阅mdma的答案)可能有所帮助。或者,您可以尝试使用“in”语句批量处理所需的interfaceID,并为每100个interfaceID运行一个查询,而不是每个都有一个。
编辑:作为一个好的做法,您应该始终使用PreparedStatement,因为它将正确处理日期等数据类型,因此您不必担心将它们格式化为正确的SQL语法。还可以防止SQL注入。
答案 2 :(得分:0)
从你看起来很多选择的问题开始(根据你的文件大小,甚至是100) 而不是这样做,而是从输入文件创建所有interfaceId值的逗号分隔列表,然后使用“IN”关键字进行1次SQL调用。你知道performanceTable,startTime和endTime没有改变,所以查询看起来像这样
SELECT d.dtime,d.ifInOctets, d.ifOutOctets
FROM MyTable_1_60 as d
WHERE dtime BETWEEN '08/14/2010' AND '08/15/2010'
AND d.id IN ( 10, 18, 25, 13, 75 )
然后您可以自由打开文件,一次性转储结果集。