我试图从 java 中的 sql 数据库中读出一列,我希望结果以数组的形式返回。这是函数:
public static double[] open(Connection conn,String symbol,int startdate,int enddate) throws SQLException {
int id = database.get_stockid(conn, symbol);
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select price_open from stock_data where stock_id="+id+" and date>="+startdate+" and date<="+enddate+";");
ArrayList<Double> data = new ArrayList<Double>();
while(rs.next()) {
data.add(rs.getDouble("open"));
}
double[] data1 = new double[data.size()];
for(int a = 0; a < data1.length; ++a) {
data1[a]=data.get(a);
}
return data1;
}
这很慢。我的 sqlite 数据库需要 1.5 秒。这是读出专栏的标准方法还是我做错了什么?这是我的应用程序的瓶颈,所以我需要它尽可能快。
编辑: 谢谢。我刚刚发现 ArrayList 没有引起问题。瓶颈肯定出在sql部分: 如果我只加载 10 天的数据,那么加载数据所需的时间与加载 10 年的数据一样长。所以我必须改进我的 sql,但是如何改进呢??
这里是改进后的代码:
public static double[] open(Connection conn,String symbol,int startdate,int enddate) throws SQLException {
int id = database.get_stockid(conn, symbol);
PreparedStatement stat = conn.prepareStatement("select price_open from stock_data where (stock_id="+id +") and (date between "+startdate+" and "+enddate+");");
ResultSet rs = stat.executeQuery();
ArrayList<Double> data = new ArrayList<Double>();
while(rs.next()) {
data.add(rs.getDouble(1));
}
double[] data1 = new double[data.size()];
for(int a = 0; a < data1.length; ++a) {
data1[a]=data.get(a);
}
return data1;
}
最佳答案
替换
double[] data1 = new double[data.size()]; for(int a = 0; a < data1.length; ++a) { data1[a]=data.get(a); }
与
double[] data1 = data.toArray(new double[data.size()]);
检查查询运行时间是多少(通过分析此应用程序或在数据库端投资日志),检查它是否可以减少,例如在
where
子句 i.d. 中使用的列上引入索引。stock_id
和date
。如果您能够估计您的查询将返回的记录数量,或者您知道它将至少有 N 条记录,那么可以代替:
ArrayList<Double> data = new ArrayList<Double>();
调用:
ArrayList<Double> data = new ArrayList<Double>(AMOUNT_OF_RECORDS);
这将允许阻止
ArrayList
的扩展(创建一个更大的新数组并将元素从较小的数组复制到新的更大的数组)。顺便说一句。对于
ArrayList
类,默认初始容量为 10。您的查询返回的结果是否唯一?也许查询返回的大部分值都是重复的?如果是,则将
DISTINCT
关键字附加到您的查询中:select distinct price_open from stock_data ...
这将节省与数据库通信的时间,返回的结果也更少,需要处理的结果也更少。
使用
PreparedStatement
而不是Statement
来:- 防止SQL注入(inject)
- 还因为性能,因为使用
PreparedStatement
允许数据库重用已经解析的查询
更新 #1
- 记住总是释放所有资源,i.d.
ResultSet
和PreparedStatement
。- 在 Java 1.7+ 中,您可以使用新的 try-with-resources 语句 ( The Java® Language Specification )
- 在旧的 Java 版本中,您必须在
finally
block 中调用close
方法,并对每个调用进行单独的异常处理,以防止出现异常情况在第一个close
中抛出会阻止调用第二个close
。
关于Java:如何有效地从数据库中读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16753434/