Come faccio a persistere i dati del disco, e sia casuale di un aggiornamento e di flusso, in modo efficiente in RAM?

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

Domanda

Ho bisogno di memorizzare fino a decine o addirittura centinaia di milioni di pezzi di dati su disco.Ogni pezzo di dati che contiene informazioni come:

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

Nuovi pezzi di dati che possono essere aggiunti al ritmo di 1 al millisecondo.

Quindi è un relativamente semplice insieme di coppie chiave-valore, dove i valori possono essere stringhe, numeri interi, o galleggianti.Occasionalmente, potrebbe essere necessario aggiornare il foglio di dati con un determinato id, cambiando il campo flag da 0 a 1.In altre parole, ho bisogno di essere in grado di fare casuale ricerche chiave con l'id e modificare i dati (in realtà solo il punto mobile "risultato" di campo - così non avrai mai bisogno di modificare la dimensione del valore).

L'altro requisito è che ho bisogno di essere in grado di trasmettere dati dal disco (l'ordine non è particolarmente importante) in modo efficiente.Questo significa che la testina del disco rigido non dovrebbe avere bisogno di saltare tutto il disco per leggere i dati, piuttosto dovrebbe essere letto consecutivi blocchi del disco.

Sto scrivendo questo in Java.

Ho pensato di usare un database incorporato, ma DB4O non è un'opzione, come è GPL e il resto del mio codice non è.Ho anche preoccuparsi circa l'efficacia dell'utilizzo di un embedded SQL database, dato il sovraccarico di tradurre da e query SQL.

Qualcuno ha qualche idea?Avrei potuto creare una soluzione personalizzata per questo (dove ho a che fare direttamente con ByteBuffers, e di gestire la ricerca dell'id)?

È stato utile?

Soluzione 7

Alla fine ho deciso di registrare i dati su disco come si entra, e anche di evitare in memoria dove posso aggiornarlo. Dopo un periodo di tempo che scrivo i dati su disco e cancellare il registro.

Altri suggerimenti

Come su H2 ? Il Licenza dovrebbe funzionare per voi.

  • È possibile utilizzare H2 gratuitamente. Puoi integrarlo nella vostra applicazione (Comprese le applicazioni commerciali), ed è possibile distribuirlo.
  • File che contiene soltanto il codice non sono coperto da questa licenza (è 'Amichevole commerciali').
  • Modifiche al codice sorgente H2 deve essere pubblicato.
  • Non è necessario fornire il codice sorgente di H2, se non l'avete fatto modificare nulla.

ho

1000000 inserto in 22492ms (44.460,252534234394 riga / sec)

100000 aggiornamenti nella 9565ms (10.454,783063251438 riga / sec)

da

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 è un grande database embedded per Java (e non come ingombro di concessione di licenze come la versione Java di Berkley). Sarebbe la pena di provare. Se non avete bisogno di garanzie ACID (vale a dire sei OK con il database venire corrotto in caso di incidente), spegnere il gestore delle transazioni (aumenta in modo significativo la velocità).

Penso che avrebbe molto più successo di scrivere qualcosa che memorizza la maggior parte dei record attivi in memoria e code di modifiche ai dati come priorità bassa inserire nel DB.

Capisco che c'è un leggero aumento IO uso questo metodo, ma se si sta parlando di milioni di record, penso che sarebbe ancora più veloce perché qualsiasi algoritmo di ricerca si crea sta per essere notevolmente superato da un un vero e proprio motore di database.

Si potrebbe provare a Berkley DB che è ora di proprietà di Oracle . Hanno Open Source e licenze commerciali. Si utilizza un modello chiave / valore (con la possibilità di creare indici se sono necessarie altre forme di query). C'è una versione di Java puro e una versione nativa con binding Java.

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

database SQLite (dominio pubblico), connettore JDBC con licenza BSD, nativo per tutta una serie di piattaforme (OSX, Linux, Windows), di emulazione per il resto.

È possibile utilizzare Apache Derby (o JavaDB) che viene fornito in bundle con JDK. Tuttavia, se un DBMS non fornisce la velocità richiesta è possibile implementare una struttura di file specifico da soli. Se è necessaria solo la ricerca di chiavi esatto, è possibile utilizzare un hash file per la sua attuazione. Il file hash è la struttura dei file più veloce per tali esigenze (molto più veloce di strutture di file finalità generali come B-Alberi e griglie che vengono utilizzati nel DB). Esso fornisce anche accettabile efficienza streaming.

Avete dato un'occhiata al database 'TimesTen' di Oracle? Il suo db un in-memory che dovrebbe essere molto ad alte prestazioni. Non so circa i costi / licenze, ecc, ma dare un'occhiata al sito Oracoli e la ricerca di esso. scaricare Eval dovrebbe essere disponibile.

Mi piacerebbe anche dare un'occhiata per vedere se c'è qualcosa di esistente basata o EHCache o JCS che potrebbe aiutare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top