2009-08-13 72 views
2

我需要在磁盤上存儲多達數十甚至數百萬的數據。每條數據包含如下信息:如何將數據保存到磁盤,並且隨機更新數據並將其高效地傳回RAM?

id=23425 
browser=firefox 
ip-address=10.1.1.1 
outcome=1.0 

新的數據片段可以以每毫秒最多1個的速率添加。

所以它是一組相對簡單的鍵值對,其中的值可以是字符串,整數或浮點數。有時候我可能需要用特定的id更新數據片段,將標誌字段從0更改爲1.換句話說,我需要能夠通過id進行隨機密鑰查找,並修改數據(實際上只是浮點數點「結果」字段 - 所以我永遠不需要修改值的大小)。

另一個要求是我需要能夠有效地從磁盤上流這個數據(順序並不特別重要)。這意味着硬盤磁頭不需要繞過磁盤來讀取數據,而應該在連續的磁盤塊中讀取數據。

我正在用Java寫這篇文章。

我想過使用嵌入式數據庫,但DB4O不是一個選項,因爲它是GPL,而我的代碼的其餘部分不是。考慮到向SQL查詢轉換和從SQL查詢轉換的開銷,我還擔心使用嵌入式SQL數據庫的效率。

有沒有人有任何想法?可能我必須爲此構建一個自定義解決方案(我直接與ByteBuffers打交道,並處理id查找)?

+0

「DB4O不是一個選項,因爲它是GPL,我的其他代碼不是」 - 只有在您計劃分發代碼時才重要。 – 2009-08-14 03:13:25

+0

我打算分發我的代碼 – sanity 2009-08-14 03:42:18

回答

0

最後,我決定將數據記錄到磁盤中,並將它保存在內存中,以便我可以更新它。一段時間後,我將數據寫入磁盤並刪除日誌。

0

我想你會有更多的成功,寫一些緩存內存中最活躍的記錄和隊列數據更改作爲低優先級插入到數據庫中。

我知道使用這種方法的IO有輕微的增加,但是如果你在談論數百萬條記錄,我認爲它會更快,因爲你創建的任何搜索算法都將大大超過完全成熟的數據庫引擎。

0

您可以試試,現在Oracle擁有它。他們擁有開源和商業許可證。它使用鍵/值模型(如果需要其他形式的查詢,可以選擇創建索引)。有一個純Java版本和一個帶有Java綁定的本地版本。

+0

我希望我能找到一些免費的東西,不幸的是,除非我願意GPL我的代碼,否則Berkeley DB不是一種選擇。 – sanity 2009-08-14 03:43:09

2

H2怎麼樣? License應該適合你。

  • 您可以免費使用H2。您可以將 集成到您的應用程序 (包括商業應用程序), ,您可以分發它。
  • 文件 只包含你的代碼是不是 該許可證所覆蓋(這是 「商業友好」)。
  • 修改爲 的H2源代碼必須爲 發佈。
  • 如果你沒有 修改任何東西,你不需要提供H2的源代碼 。

我得到了22492ms(44460.252534234394行/秒)

100000更新在9565ms(10454.783063251438行/秒)

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.SQLException; 
import java.util.Random; 


/** 
* @author clint 
* 
*/ 
public class H2Test { 

    static int testrounds = 1000000; 

    public static void main(String[] args) { 
    try { 
     Class.forName("org.h2.Driver"); 

    Connection conn = DriverManager. 
     getConnection("jdbc:h2:/tmp/test.h2", "sa", ""); 
    // add application code here 
    conn.createStatement().execute("DROP TABLE IF EXISTS TEST"); 
    conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TEST(id INT PRIMARY KEY, browser VARCHAR(64),ip varchar(16), outcome real)"); 
    //conn.createStatement().execute("CREATE INDEX IDXall ON TEST(id,browser,ip,outcome"); 


    PreparedStatement ps = conn.prepareStatement("insert into TEST (id, browser, ip, outcome) values (?,?,?,?)"); 
    long time = System.currentTimeMillis(); 
    for (int i = 0; i < testrounds; i++) { 
     ps.setInt(1,i); 
     ps.setString(2,"firefox"); 
     ps.setString(3,"000.000.000.000"); 
     ps.setFloat(4,0); 
     ps.execute(); 
    } 
    long last = System.currentTimeMillis() ; 
    System.out.println(testrounds + " insert in " + (last - time) + "ms (" + ((testrounds)/((last - time)/1000d)) + " row/sec)"); 

    ps.close(); 
    ps = conn.prepareStatement("update TEST set outcome = 1 where id=?"); 
    Random random = new Random(); 
    time = System.currentTimeMillis(); 

    /// randomly updadte 10% of the entries 
    for (int i = 0; i < testrounds/10; i++) { 
     ps.setInt(1,random.nextInt(testrounds)); 
     ps.execute(); 
    } 

    last = System.currentTimeMillis(); 
    System.out.println((testrounds/10) + " updates in " + (last - time) + "ms (" + ((testrounds/10)/((last - time)/1000d)) + " row/sec)"); 

    conn.close(); 

    } catch (ClassNotFoundException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (SQLException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    } 

} 

百萬插入

-1

我會所以請看看是否存在基於EHCache或JCS的任何可能的幫助。

0

您可以使用與JDK捆綁在一起的Apache Derby(或JavaDB)。但是,如果DBMS不提供所需的速度,則可以自己實現特定的文件結構。如果只需要精確的密鑰查找,則可以使用散列文件來實現它。散列文件是這種需求的最快文件結構(比通用文件結構(例如DB中使用的B樹和網格)快得多)。它還提供可接受的流媒體效率。

1

JDBM是一個偉大的Java嵌入式數據庫(並不像Berkley的Java版本那樣受到許可限制)。這將是值得嘗試的。如果您不需要ACID保證(即在發生崩潰時數據庫可能損壞),請關閉事務管理器(顯着提高速度)。

0

你看過Oracle的'TimesTen'數據庫嗎?它的內存分貝應該是非常高性能的。不知道費用/許可證等,但看看Oracles網站並搜索它。評估下載應該可用。

相關問題