简体   繁体   English

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

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

Im trying to read out a column from an sql database in java, I want the result to be returned in an array. 我试图从java中的sql数据库中读出一列,我希望结果在数组中返回。 Here is the function: 这是功能:

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;
}

This is quite slow. 这很慢。 It Takes 1.5 secs with my sqlite database. 它使用我的sqlite数据库需要1.5秒。 Is this the standard way to read out a column or am I doing something wrong? 这是读取列的标准方法还是我做错了什么? This is the bottleneck in my application, so I need it to be as fast as possible. 这是我的应用程序的瓶颈,所以我需要它尽可能快。


edited: thanks. 编辑:谢谢。 I just found out that the ArrayList is not causing the problem. 我刚刚发现ArrayList没有引起问题。 The bottleneck must lie in the sql part: If I load data for just 10 days it takes as long as loading data for 10 years. 瓶颈必须在于sql部分:如果我加载数据仅10天就需要加载数据10年。 SO I have to improve on my sql but how?? 所以我必须改进我的SQL,但如何?

Here the improved code: 这里改进了代码:

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. Replace 更换

     double[] data1 = new double[data.size()]; for(int a = 0; a < data1.length; ++a) { data1[a]=data.get(a); } 

    with

     double[] data1 = data.toArray(new double[data.size()]); 
  2. Check what is the query running time (by profiling of this application or investing the logs on the database side), check if it can be reduced by eg introducing indexes on the columns used in the where clause id stock_id and date . 检查查询运行时间是什么(通过分析此应用程序或将日志投入数据库端),检查是否可以通过在where子句id stock_iddate使用的列上引入索引来减少它。

  3. If you are able to estimate the amount of records your query will return or you know that it will be at least N records then instead of: 如果您能够估计查询将返回的记录数量,或者您知道它将至少为N条记录,则代替:

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

    invoke: 引用:

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

    this will allow to prevent expanding of the ArrayList (creating a new array of greater size and copying of the elements from the smaller array to the new bigger array). 这将允许防止扩展ArrayList (创建一个更大的新数组并将元素从较小的数组复制到新的更大的数组)。

    BTW. BTW。 For the ArrayList class the default initial capacity is 10. 对于ArrayList类,默认初始容量为10。

  4. Are the results returned from your query unique? 从您的查询返回的结果是唯一的吗? Maybe most of the values returned from the query are duplicated? 也许从查询返回的大多数值都是重复的? If yes, then append the DISTINCT keyword to your query: 如果是,则将DISTINCT关键字附加到您的查询:

     select distinct price_open from stock_data ... 

    this will allow to save the time on the communication with the database and also less results returned, less results have to be processed. 这样可以节省与数据库通信的时间,并且返回的结果也更少,必须处理的结果更少。

  5. Use PreparedStatement instead of Statement to: 使用PreparedStatement而不是Statement来:

    • protect from the SQL injection 防止SQL注入
    • but also because of performance, as using PreparedStatement allows the database to reuse the already parsed query 而且由于性能的原因,使用PreparedStatement允许数据库重用已经解析的查询

Update #1 更新#1

  1. Remember to always free all the resources, id ResultSet and PreparedStatement . 请记住始终释放所有资源,id ResultSetPreparedStatement
    • In Java 1.7+, you can use the new try-with-resources statement ( The Java® Language Specification ) 在Java 1.7+中,您可以使用新的try-with-resources语句( Java®语言规范
    • In older Java versions, you have to put calls to the close methods in the finally block and have separate exception handling for each call to prevent a scenario when an exception thrown in the first close prevents the second close from being called. 在较旧的Java版本中,您必须对finally块中的close方法进行调用,并对每个调用进行单独的异常处理,以防止在第一个close抛出异常时阻止第二个close被调用的情况。

Your query is: 您的查询是:

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

To optimize this, create an index on stock_data(stock_id, date) . 要优化此操作,请在stock_data(stock_id, date)上创建索引。 The index lookup will be used to fetch the data. 索引查找将用于获取数据。

If your data is really large, then you can have the index on stock_data(stock_id, date, price_open) . 如果您的数据非常大,那么您可以在stock_data(stock_id, date, price_open)stock_data(stock_id, date, price_open)索引。 These are the only three columns referenced in the query, so the index can satisfy the query without having to load the original data pages. 这些是查询中引用的唯一三列,因此索引可以满足查询而无需加载原始数据页。

You can improve performance by using a primitive array instead of ArrayList, but this requires that you know how large the result set is. 您可以使用原始数组而不是ArrayList来提高性能,但这需要您知道结果集的大小。

Refer to columns by index instead of name - this can also offer a slight improvement. 按索引而不是名称引用列 - 这也可以略微改进。

 datars.getDouble(1);

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

相关问题 如何使用Java NIO从套接字高效读取 - How to read efficiently from socket using Java NIO 在URL中有效地将文件从URL读入byte [] - Efficiently read file from URL into byte[] in Java 如何在Java中有效读取大型文本文件 - How to read the large text files efficiently in java 如何从 Firebase 数据库中读取数据? - 爪哇 - How to read data from Firebase Database? - Java 在Java中,如何有效地从文件中读取x行,将其关闭,然后从x行开始再次打开它并继续读取 - in java how to efficiently read x lines from a file, close it, and then open it again, starting at line x and continue reading 如何在Java Server中从Apple Push Notifications Server可靠而有效地读取所有错误响应? - How to reliably and efficiently read all error responses from Apple Push Notifications Server in a Java Server? Java Spring:如何有效地从CSV文件读取和保存大量数据? - Java Spring: How to efficiently read and save large amount of data from a CSV file? 如何有效地将数据从 CSV 加载到数据库中? - How to efficiently load data from CSV into Database? 如何有效地从数据库检索数据? - How to retrieve data from a database efficiently? 是否有Java版本的EGLImage可以有效地从OpenGL读取像素? - Is there a java version of EGLImage to read pixel from OpenGL efficiently?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM