繁体   English   中英

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

[英]Java: How to efficiently read from database?

我试图从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;
}
  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. 检查查询运行时间是什么(通过分析此应用程序或将日志投入数据库端),检查是否可以通过在where子句id stock_iddate使用的列上引入索引来减少它。

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

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

    引用:

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

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

    BTW。 对于ArrayList类,默认初始容量为10。

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

     select distinct price_open from stock_data ... 

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

  5. 使用PreparedStatement而不是Statement来:

    • 防止SQL注入
    • 而且由于性能的原因,使用PreparedStatement允许数据库重用已经解析的查询

更新#1

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

您的查询是:

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)stock_data(stock_id, date, price_open)索引。 这些是查询中引用的唯一三列,因此索引可以满足查询而无需加载原始数据页。

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

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

 datars.getDouble(1);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM