¿Cómo puedo guardar los datos en el disco, y ambos actualizar al azar, y transmitirla de manera eficiente hacia atrás en la memoria RAM?

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

Pregunta

Necesito almacenar hasta decenas o incluso cientos de millones de piezas de datos en disco. Cada pieza de datos contiene información como:

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

Plantillas de piezas de datos pueden ser añadidos a una tasa de hasta al 1 por milisegundo.

Así que es un conjunto relativamente simple de pares clave-valor, donde los valores pueden ser cadenas, enteros o flotadores. De vez en cuando puede ser necesario actualizar la hoja de datos con una identificación especial, cambiando el campo de la bandera de 0 a 1. En otras palabras, tengo que ser capaz de hacer búsquedas de claves aleatorias por id, y modificar los datos (en realidad sólo la flotación punto de campo "resultado" - por lo que nunca tendrá que modificar el tamaño del valor)

.

El otro requisito es que tengo que ser capaz de transmitir estos datos fuera del disco (el orden no es particularmente importante) de manera eficiente. Esto significa que la cabeza del disco duro no debería necesitar para saltar alrededor del disco para leer los datos, sino que debe ser entendida en bloques de disco consecutivos.

Estoy escribiendo esto en Java.

He pensado en el uso de una base de datos integrada, pero DB4O no es una opción, ya que es GPL y el resto de mi código no es. También me preocupa la eficiencia de la utilización de una base de datos de SQL incorporado, dada la sobrecarga de traducir desde y hacia las consultas SQL.

¿Alguien tiene alguna idea? ¿Puedo tener que construir una solución personalizada a esta (donde estoy tratando directamente con ByteBuffers, y gastos de las operaciones de búsqueda ID)?

¿Fue útil?

Solución 7

Al final decidí registrar los datos en el disco, ya que entra, y también mantener en la memoria donde puedo actualizarlo. Después de un período de tiempo que escriba los datos en el disco y borrar el registro.

Otros consejos

¿Qué hay de H2 ? El Licencia debe trabajar para usted.

  • Puede utilizar H2 de forma gratuita. Usted puede integrarlo en su aplicación (Incluidas las aplicaciones comerciales), y se puede distribuirlo.
  • Archivos que contiene sólo el código no son cubierto por esta licencia (es 'Amigable comercial').
  • Modificaciones El código fuente debe ser H2 publicado.
  • No es necesario para proporcionar el código fuente de H2 si no lo hizo modificar nada.

consigo

1000000 inserto en 22492ms (44460.252534234394 fila / seg)

100000 actualizaciones en 9565ms (10454.783063251438 fila / seg)

de

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 es una gran base de datos integrada para Java (y no como gravados con la concesión de licencias como la versión Java de Berkley). Sería vale la pena probar. Si usted no necesita garantías ACID (es decir, estás bien con la base de datos conseguir dañado en el caso de un accidente), apague el administrador de transacciones (aumenta significativamente la velocidad).

Creo que tendría mucho más éxito escribiendo algo que almacena en caché los registros más activos en los cambios de datos de la memoria y las colas como un inserto de baja prioridad en la base de datos.

Tengo entendido que hay un ligero aumento en IO utilizando este método, pero si usted está hablando de millones de registros Creo que aún sería más rápido, ya que cualquier algoritmo de búsqueda se crea va a ser superado en gran medida por aa motor de base de datos completa hecha y derecha.

Usted podría intentar Berkeley DB, que ahora es propiedad de Oracle . Tienen código abierto y licencias comerciales. Se utiliza un modelo de clave / valor (con la opción de crear índices si se requieren otras formas de consultas). Hay una versión de Java puro y una versión nativa con enlaces Java.

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

base de datos SQLite (dominio público), conector JDBC con licencia BSD, nativo para un montón de plataformas (OSX, Linux, Windows), emulación para el resto.

Puede utilizar Apache Derby (o JavaDB), que se proporciona con el JDK. Sin embargo, si un DBMS no proporciona la velocidad requerida es posible implementar una estructura de archivos específica usted mismo. Si sólo se requiere exacta búsqueda de claves, es posible utilizar un hash de archivo para ponerlo en práctica. El archivo hash es la estructura de archivos más rápida para tales requisitos (mucho más rápido que las estructuras generales de archivos con fines tales como B-árboles y las redes que se utilizan en DB). También proporciona la eficiencia de streaming aceptable.

¿Se ha tomado un vistazo a la base de datos de Oracle TimesTen '? Su db una en memoria que se supone que es de muy alto rendimiento. No sé acerca de los costos / licencias, etc., pero echa un vistazo a los oráculos sitio y la búsqueda de la misma. Descargar la evaluación debe estar disponible.

También me gustaría echar un vistazo para ver si hay algo existente basada en cualquiera EHCache o JCS que podría ayudar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top