Java:如何有效地从数据库中读取?

时间:2013-05-25 20:06:27

标签: java sql performance

我试图从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;
}

3 个答案:

答案 0 :(得分:5)

  1. 替换

    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()]);
    
  2. 检查查询运行时间是什么(通过分析此应用程序或将日志投入数据库端),检查是否可以通过例如在i where子句中使用的列上引入索引。 stock_iddate

  3. 如果您能够估计查询将返回的记录数量,或者您知道它将至少是N条记录,而不是:

    ArrayList<Double> data = new ArrayList<Double>();
    

    调用:

    ArrayList<Double> data = new ArrayList<Double>(AMOUNT_OF_RECORDS);
    

    这将允许防止扩展ArrayList(创建一个更大的新数组并将元素从较小的数组复制到新的更大的数组)。

    顺便说一句。对于ArrayList类,默认初始容量为10.

  4. 查询返回的结果是唯一的吗?也许从查询返回的大多数值都是重复的?如果是,请将DISTINCT关键字附加到您的查询中:

    select distinct price_open from stock_data ...
    

    这样可以节省与数据库通信的时间,也可以减少返回的结果,减少必须处理的结果。

  5. 使用PreparedStatement代替Statement

    • 保护免受SQL注入
    • 但也因为性能,因为使用PreparedStatement允许数据库重用已经解析的查询

  6. 更新#1

    1. 请记住始终释放所有资源,i.d。 ResultSetPreparedStatement
      • 在Java 1.7+中,您可以使用新的try-with-resources语句(The Java® Language Specification
      • 在较旧的Java版本中,您必须对close块中的finally方法进行调用,并为每个调用分别进行异常处理,以防止在第一个{close中抛出异常的情况1}}阻止第二个close被调用。

答案 1 :(得分:2)

您的查询是:

select price_open
from stock_data
where stock_id="+id+" and date>="+startdate+" and date<="+enddate+"

要优化此功能,请在stock_data(stock_id, date)上创建索引。索引查找将用于获取数据。

如果您的数据非常大,那么您可以在stock_data(stock_id, date, price_open)上设置索引。这些是查询中引用的唯一三列,因此索引可以满足查询而无需加载原始数据页。

答案 2 :(得分:1)

您可以使用基本数组而不是ArrayList来提高性能,但这需要您知道结果集的大小。

按索引而不是名称引用列 - 这也可以略微改进。

 datars.getDouble(1);