Wie bestehen wir Daten auf der Festplatte, und sowohl sie nach dem Zufall aktualisieren, und es in dem RAM effizient zurück zu streamen?

StackOverflow https://stackoverflow.com/questions/1274562

Frage

Ich muß Zehner speichern oder sogar Hunderte von Millionen von Stücken von Daten auf der Festplatte. Jedes Stück Daten enthalten Informationen wie:

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

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

So ist es relativ einfacher Satz von Schlüssel-Wert-Paaren, wobei die Werte können Strings, Integer oder Schwimmer sein. Gelegentlich kann ich brauche das Stück von Daten mit einer bestimmten ID zu aktualisieren, das Flag-Feld Mit anderen Worten: von 0 auf 1 ändert, muss ich zufälligen Schlüssel-Lookups von id tun zu können, und die Daten ändern (eigentlich nur die Schwimm Punkt „Ausgang“ Feld - so werde ich nie brauchen, um die Größe des Wertes) ändern

.

Die andere Bedingung ist, dass ich diese Daten in der Lage sein müssen Platte streamen aus (die Reihenfolge nicht besonders wichtig ist) effizient. Das bedeutet, dass der Festplattenkopf sollte nicht um die Platte springen muß, um die Daten zu lesen, sondern es sollte in aufeinanderfolgenden Plattenblöcken gelesen werden.

Ich schreibe dies in Java.

Ich habe darüber nachgedacht, eine eingebettete Datenbank verwenden, aber DB4O ist keine Option, da es GPL und der Rest meines Code ist nicht. Ich mache mir Sorgen auch um die Effizienz eine eingebettete SQL-Datenbank verwenden, da der Aufwand für die Übersetzung zu und von SQL-Abfragen.

Hat jemand irgendwelche Ideen? Kann ich habe eine benutzerdefinierte Lösung für dieses Problem zu bauen (wo ich direkt mit ByteBuffers und Umgang mit dem ID-Lookup zu tun)?

War es hilfreich?

Lösung 7

Am Ende habe ich beschlossen, die Daten auf der Festplatte zu protokollieren, wie es kommt, und es ist auch in Erinnerung behalten, wo ich es aktualisieren kann. Nach einer gewissen Zeit schreibe ich die Daten auf die Festplatte und das Protokoll löschen.

Andere Tipps

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

  • Sie können H2 verwenden kostenlos. Du kannst Integration in die Anwendung (Einschließlich kommerziellen Anwendungen), und Sie können es verteilen.
  • Dateien nur Ihren Code enthalten, sind nicht durch diese Lizenz abgedeckt (es ist ‚Handel freundlich‘).
  • Änderungen Um den Quellcode H2 muss sein veröffentlicht.
  • Sie brauchen nicht zu schaffen, der Quellcode von H2, wenn Sie nicht tun ändert nichts.

ich

1000000 Einsatz in 22492ms (44460,252534234394 Reihe / s)

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

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

}

JDBM ist eine große eingebettete Datenbank für Java (und nicht wie bei der Lizenzierung als Java-Version belastet Berkley). Es wäre ein Versuch wert. Wenn Sie nicht ACID Garantien benötigen (das heißt Sie mit der Datenbank in Ordnung sind immer im Falle eines Aufpralls beschädigt), die Transaktions-Manager ausschalten (deutlich Geschwindigkeit erhöht).

Ich denke, dass Sie viel mehr Erfolg etwas zu schreiben haben würden, die die meist aktiven Datensätze im Speicher und Warteschlangen Datenänderungen als niedrige Priorität Einsatz in die DB-Caches.

Ich verstehe, gibt es einen leichten Anstieg der IO mit dieser Methode aber wenn Sie sprechen sind Millionen von Datensätzen Ich denke, es noch schneller sein würde, weil jeder Suchalgorithmus Sie erstellen, wird stark durch aa vollwertigen Datenbank-Engine übertrafen gehen werden.

Sie könnten versuchen, Berkley DB die nun von Oracle gehört . Sie haben Open Source und kommerzielle Lizenzen. Es verwendet ein Schlüssel / Wert-Modell (mit einer Option Indizes zu erstellen, wenn andere Formen von Abfragen erforderlich sind). Es ist eine reine Java-Version und eine native Version mit Java-Bindungen.

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.

Sie können mit Apache Derby (oder JavaDB), die mit JDK gebündelt. Wenn jedoch ein DBMS die gewünschte Geschwindigkeit nicht bieten können Sie eine bestimmte Dateistruktur selbst implementieren. Wenn nur genaue Schlüsselsuche erforderlich ist, können Sie eine Hash-Datei, um sie zu implementieren, verwenden. Die Hash-Datei ist die schnellste Dateistruktur für solche Anforderungen (viel schneller als Allzweck-Dateistrukturen wie B-Bäume und Gitter, die in DBs verwendet werden). Es bietet auch akzeptabel Streaming-Effizienz.

Haben Sie einen Blick auf Oracle ‚TimesTen‘ Datenbank genommen? Es ist eine In-Memory-db, die angeblich sehr hohe Leistung. Sie wissen nicht, über Kosten / Lizenzen, etc., aber einen Blick auf Oracles Website nehmen und danach suchen. Eval-Download zur Verfügung steht.

ich auch einen Blick darauf werfen würde, um zu sehen, ob es etwas gibt, auf bestehende Basis entweder EHCache oder JCS, die helfen können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top