2013-05-25 73 views
4

我試圖從Java中的SQL數據庫讀出一列,我想結果返回到一個數組中。這裏是功能:Java:如何有效地從數據庫中讀取?

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

這很慢。它需要1.5秒與我的sqlite數據庫。這是讀出一列的標準方式,還是我做錯了什麼?這是我應用程序中的瓶頸,所以我需要它儘可能快。


編輯: 謝謝。我剛發現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

您的查詢選擇'price_open',但您的ResultSet調用'getDouble(「open」)''。這實際上是否按預期工作?另外,您一次獲取多少行數據? – Vulcan

+0

首先,讓你的查詢運行得很快。 – ntalbs

+1

您的數據庫是否已正確編入索引? – Supericy

回答

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. 檢查什麼是運行時間查詢(此應用程序的分析或投資洛杉磯gs在數據庫方面),檢查它是否可以被減少。在where子句i.d中使用的列上引入索引。 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允許數據庫重用已解析的查詢

更新# 1

  1. 請記住永遠免費的所有資源,i.d. ResultSetPreparedStatement
    • 在Java 1.7+,你可以使用新的嘗試,與資源的語句(The Java® Language Specification
    • 在舊的Java版本,你必須付諸close方法的調用在finally塊,並有單獨的異常處理每次調用以防止在第一個close中拋出的異常阻止調用第二個close時發生的情況。
+0

幫助SQL注入,是的。回答這個問題?沒那麼多。 – Makoto

+0

@Makoto我太快了,再加兩個點,但是'PreparedStatement'應該不僅僅是因爲SQL注入的保護。 –

+0

使用'java.util.List'更有效,* ArrayList *,+1是一個很好的答案。 – Azad

1

可以提高使用基本數組,而不是ArrayList的性能,但是這需要你知道結果集有多大。

請參閱通過索引​​而不是名稱列 - 這也可以提供一些改進。

datars.getDouble(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)上獲得索引。這些是查詢中引用的唯一三列,因此索引可以滿足查詢而無需加載原始數據頁面。

相關問題