2009-08-13 4 views
2

Ich muss bis zu Dutzende oder sogar Hunderte von Millionen von Daten auf der Festplatte speichern. Jedes Stück Daten enthält Informationen wie:Wie behalte ich Daten auf der Festplatte, und beide aktualisieren sie zufällig und streamen sie effizient zurück in den Arbeitsspeicher?

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

Neue Stücke von Daten können mit einer Geschwindigkeit von bis zu 1 pro Millisekunde hinzugefügt werden.

Also eine relativ einfache Gruppe von Schlüssel-Wert-Paaren, wobei die Werte Strings, Integer oder Floats sein können. Gelegentlich muss ich möglicherweise das Datenstück mit einer bestimmten ID aktualisieren, indem ich das Flag-Feld von 0 auf 1 ändere. Mit anderen Worten, ich muss in der Lage sein, zufällige Schlüsselsuchen nach ID durchzuführen und die Daten zu modifizieren (eigentlich nur das Floating) Punkt "Ergebnis" Feld - so werde ich nie die Größe des Wertes ändern müssen.

Die andere Voraussetzung ist, dass ich in der Lage sein muss, diese Daten von der Festplatte (die Reihenfolge ist nicht besonders wichtig) effizient zu streamen. Dies bedeutet, dass der Festplattenkopf nicht um die Platte herumspringen muss, um die Daten zu lesen, sondern dass er in aufeinander folgenden Plattenblöcken gelesen werden sollte.

Ich schreibe dies in Java.

Ich habe über die Verwendung einer eingebetteten Datenbank nachgedacht, aber DB4O ist keine Option, da es GPL ist und der Rest meines Codes nicht ist. Ich mache mir auch Sorgen über die Effizienz der Verwendung einer eingebetteten SQL-Datenbank angesichts des Overheads der Übersetzung von und zu SQL-Abfragen.

Hat jemand irgendwelche Ideen? Könnte ich eine benutzerdefinierte Lösung dafür erstellen (wo ich direkt mit ByteBuffers beschäftigen und die ID-Lookup)?

+0

"DB4O ist keine Option, da es GPL ist und der Rest meines Codes ist nicht" - das ist nur wichtig, wenn Sie planen, Ihren Code zu verteilen. –

+0

Ich plane, meinen Code – sanity

Antwort

0

Am Ende entschied ich mich, die Daten auf der Festplatte zu protokollieren, wie es kommt, und auch im Speicher zu behalten, wo ich es aktualisieren kann. Nach einer gewissen Zeit schreibe ich die Daten auf die Festplatte und lösche das Protokoll.

0

Ich denke, Sie hätten viel mehr Erfolg beim Schreiben von etwas, das die aktivsten Datensätze im Speicher zwischenspeichert und Datenänderungen als eine niedrige Priorität in die DB einfügt.

Ich verstehe, dass es einen leichten Anstieg in IO mit dieser Methode gibt, aber wenn Sie über Millionen von Aufzeichnungen sprechen, denke ich, es wäre immer noch schneller, weil jeder Suchalgorithmus wird von einer vollwertigen Datenbank-Engine stark übertroffen werden .

0

Sie könnten versuchen , die jetzt im Besitz von Oracle ist. Sie haben Open Source und kommerzielle Lizenzen. Es verwendet ein Schlüssel/Wert-Modell (mit einer Option zum Erstellen von Indizes, wenn andere Formen von Abfragen erforderlich sind). Es gibt eine reine Java-Version und eine native Version mit Java-Bindings.

+0

zu verteilen Ich hoffe, ich kann etwas frei finden, leider Berkeley DB ist nicht, wenn ich bereit bin, meinen Code GPL, der keine Option ist. – sanity

0

http://www.zentus.com/sqlitejdbc/

SQLite-Datenbank (public domain), JDBC-Connector mit BSD-Lizenz, nativen für eine ganze Reihe von Plattformen (OSX, Linux, Windows), Emulation für den Rest.

2

Wie wäre es mit H2? Die sollte für Sie arbeiten.

  • Sie können H2 kostenlos verwenden. Sie können in Ihre Anwendung integrieren (einschließlich kommerzieller Anwendungen), und Sie können es verteilen.
  • Dateien mit nur Ihrem Code sind nicht durch diese Lizenz abgedeckt (es ist 'commercial friendly').
  • Änderungen zu dem H2-Quellcode muss veröffentlicht werden.
  • Sie müssen den Quellcode von H2 nicht zur Verfügung stellen, wenn Sie nicht etwas ändern.

ich

1000000 Einsatz in 22492ms (44.460,252534234394 Reihe/sec)

100000 Updates in 9565ms (10.454,783063251438 Reihe/sec)

von

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

Ich würde al Schauen Sie sich also an, ob es etwas gibt, das auf EHCache oder JCS basiert, die helfen könnten.

0

Sie können Apache Derby (oder JavaDB) verwenden, das mit JDK gebündelt ist. Wenn jedoch ein DBMS nicht die erforderliche Geschwindigkeit bereitstellt, können Sie selbst eine bestimmte Dateistruktur implementieren. Wenn nur eine exakte Schlüsselsuche erforderlich ist, können Sie eine Hash-Datei verwenden, um sie zu implementieren. Die Hash-Datei ist die schnellste Dateistruktur für solche Anforderungen (viel schneller als allgemeine Dateistrukturen wie B-Trees und Grids, die in DBs verwendet werden). Es bietet auch eine akzeptable Streaming-Effizienz.

1

JDBM ist eine großartige eingebettete Datenbank für Java (und nicht so lizenziert wie die Java-Version von Berkley). Es wäre einen Versuch wert. Wenn Sie keine ACID-Garantien benötigen (z. B. wenn die Datenbank bei einem Systemabsturz beschädigt ist), deaktivieren Sie den Transaktionsmanager (erhöht die Geschwindigkeit erheblich).

0

Haben Sie sich die "TimesTen" -Datenbank von Oracle angesehen? Es ist eine In-Memory-Datenbank, die sehr leistungsfähig sein soll. Ich weiß nicht über Kosten/Lizenzen usw., aber werfen Sie einen Blick auf Oracles Website und suchen Sie danach. Eval-Download sollte verfügbar sein.

Verwandte Themen