簡體   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