Aquí podría ser tu PUBLICIDAD


Almacenamiento persistente eficiente para un mapa simple de identificación a tabla de valores para Java

votos
5

Necesito almacenar algunos datos que siguen el patrón simple de asignar un id a una tabla completa (con varias filas) de varias columnas (es decir, algunos valores enteros [u, v, w]). El tamaño de una de estas tablas sería un par de KB. Básicamente lo que necesito es almacenar un caché persistente de algunos resultados intermedios.

Esto podría implementarse fácilmente como sql simple, pero hay un par de problemas, es decir, necesito comprimir el tamaño de esta estructura en el disco tanto como sea posible. (debido a la cantidad de valores que estoy almacenando). Además, no es transaccional, solo necesito escribir una vez y simplemente leer el contenido de toda la tabla, por lo que una base de datos relacional no es realmente una buena opción.

Me preguntaba si alguien tenía alguna buena sugerencia. Por alguna razón, parece que no puedo encontrar un cajero automático decente. Especialmente algo con una API en Java sería agradable.

Publicado el 12/03/2009 a las 16:11
fuente por usuario wds
En otros idiomas...        العربية       

7 respuestas

votos
3

¡Esto suena como un trabajo para ... new ObjectOutputStream(new FileOutputStream(STORAGE_DIR + "/" + key + ".dat");!

En serio: el método más simple es simplemente crear un archivo para cada tabla de datos que desee almacenar, serializar los datos y buscarlos usando la clave como nombre de archivo cuando quiera leer.

En un sistema de archivos decente las escrituras pueden hacerse atómicas (escribiendo en un archivo temporal y luego renombrando el archivo); la velocidad de lectura / escritura se mide en 10s de MBit / segundo; las búsquedas se pueden hacer muy eficientes al crear un árbol de directorios simple STORAGE_DIR + "/" + key.substring(0,2) + "/" + key.substring(0,4) + "/" + keyque debería ser eficiente con millones de entradas y aún más eficiente si su sistema de archivos utiliza directorios indexados; por último, es trivial implementar una memoria caché LRU respaldada por memoria además de esto para recuperaciones aún más rápidas.

Con respecto a la compresión, puede utilizar la compresión de recursos comunes de Yakarta para afectar a una compresión gzip o incluso bzip2 a los datos antes de almacenarlos. Pero este es un problema de optimización y, dependiendo de su aplicación y del espacio disponible en disco, es mejor que invierta los ciclos de la CPU en otro lado.

Aquí hay una implementación de ejemplo que hice: http://geek.co.il/articles/geek-storage.zip . Utiliza una interfaz simple (que está lejos de ser limpia, es solo una demostración del concepto) que ofrece métodos para almacenar y recuperar objetos de un caché con un tamaño máximo establecido. Una falla de caché se transfiere a una implementación de usuario para su manejo, y la caché verificará periódicamente que no excede los requisitos de almacenamiento y eliminará los datos antiguos.

También incluí una implementación respaldada por MySQL para completarla y un punto de referencia para comparar las implementaciones basadas en disco y basadas en MySQL. En mi máquina doméstica (un antiguo Athlon 64), el índice de referencia del disco obtuvo una puntuación mejor que el doble de la implementación de MySQL en el benchmark adjunto (9,01 segundos frente a 18,17 segundos). A pesar de que la implementación de la base de datos probablemente se haya modificado para obtener un rendimiento ligeramente mejor, creo que demuestra el problema lo suficientemente bien.

Siéntase libre de usar esto como mejor le parezca.

Respondida el 12/03/2009 a las 04:28
fuente por usuario Guss


Aquí podría ser tu PUBLICIDAD


votos
2

Que haría uso de EHCache , se utiliza por Hibernate y otras bibliotecas de Java EE, y es muy simple y eficiente:

Para agregar una tabla:

List<List<Integer>> myTable = new(...)
cache.put(new Element("myId", myTable));

Leer:

List<List<Integer>> myTable = (List<List<Integer>>) cache.get("myId").getObjectValue();
Respondida el 12/03/2009 a las 04:29
fuente por usuario Abdullah Jibaly

votos
1

Apache Derby podría ser una buena opción si quieres algo integrado (no un servidor separado).

Hay una lista de otras opciones en Lightweight Data Bases en Java

Respondida el 12/03/2009 a las 04:47
fuente por usuario CoverosGene

votos
1

¿Has mirado a Berkeley DB ? Eso suena como que puede encajar en la cuenta.


Editar:

Olvidé agregar que puedes descomprimir los valores antes de almacenarlos. Luego simplemente descomprímalos cuando los recuperes.

Respondida el 12/03/2009 a las 04:14
fuente por usuario grieve

votos
0

Si tiene un par de KB, no entiendo por qué necesita "comprimir el tamaño de esta estructura en el disco tanto como sea posible" Dado que 181 MB de espacio en disco cuestan 1 centavo, sugeriría que cualquier cantidad inferior a esta no vale la pena pasar demasiado tiempo preocupándose.

Sin embargo, para responder a su pregunta, puede comprimir el archivo a medida que lo escribe. Además de ObjectOutputStream, puede usar XMLExcoder para serializar su mapa. Esto será más compacto que usar ObjectOutputStream y si descomprime el archivo podrá leer o editar los datos.

XMLEncoder xe = new XMLEncoder(
    new GZIPOutputStream(
        new FileOutputStream(filename+".xml.gz")));
xe.writeObject(map);
xe.close();
Respondida el 04/04/2009 a las 12:00
fuente por usuario Peter Lawrey

votos
0

Puedes utilizar JOAFIP http://joafip.sourceforge.net/ Te permite poner todo tu modelo de datos en un archivo y puedes acceder a él, actualizarlo, sin volver a cargar todo en la memoria.

Respondida el 03/04/2009 a las 11:59
fuente por usuario luc peuvrier

votos
0

Parece que Key => Value Databases es lo que buscas.

Tal vez SuperCSV es el mejor marco para ti.

Si no desea utilizar una base de datos relacional, puede usar JAXB para almacenar sus Objetos como archivos XML.

También hay una forma con otras bibliotecas como XStream

Si prefiere XML, utilice JAXB o XStream. De lo contrario, debería echar un vistazo a las bibliotecas CSV como SuperCSV. Las personas que pueden vivir con archivos java serializados pueden usar el mecanismo de persistencia predeterminado como dijo Guss. La persistencia directa de Java puede ser la forma más rápida.

Respondida el 12/03/2009 a las 05:09
fuente por usuario Martin K.