java loading large-files large-data-volumes

java - Asesoramiento en el manejo de grandes volúmenes de datos



loading large-files (11)

Encontré que Informatica es una herramienta de procesamiento de datos excepcionalmente útil. La buena noticia es que las versiones más recientes incluso permiten transformaciones de Java. Si está lidiando con terabytes de datos, podría ser hora de ponerse al día con las mejores herramientas de ETL.

Supongo que quieres hacer algo con los resultados del procesamiento aquí, como almacenarlo en algún lado.

Así que tengo un número "grande" de archivos ASCII "muy grandes" de datos numéricos (gigabytes en total), y mi programa deberá procesar la totalidad de forma secuencial al menos una vez.

¿Algún consejo sobre almacenar / cargar los datos? He pensado en convertir los archivos en binarios para hacerlos más pequeños y para una carga más rápida.

¿Debo cargar todo en la memoria todo a la vez?
Si no, ¿está abriendo qué es una buena manera de cargar los datos parcialmente?
¿Cuáles son algunos consejos de eficiencia relevantes para Java?


Puede convertir a binario, pero luego tiene 1+ algo de copias de los datos, si necesita mantener el original.

Puede ser práctico construir algún tipo de índice sobre sus datos ascii originales, de modo que si necesita repasar los datos nuevamente puede hacerlo más rápido en los momentos posteriores.

Para responder a sus preguntas en orden:

¿Debo cargar todo en la memoria todo a la vez?

No si no es necesario. para algunos archivos, puede hacerlo, pero si solo está procesando secuencialmente, simplemente haga una especie de lectura en búfer de las cosas una a una, almacenando todo lo que necesite en el camino.

Si no, ¿está abriendo qué es una buena manera de cargar los datos parcialmente?

BufferedReaders / etc es el más simple, aunque podría examinar profundamente en FileChannel / etc para usar E / S con memoria de mapa para ir a través de las ventanas de los datos a la vez.

¿Cuáles son algunos consejos de eficiencia relevantes para Java?

¡Eso realmente depende de lo que estés haciendo con los datos en sí!


Realmente no nos has dado suficiente información para ayudarte. ¿Necesita cargar cada archivo en su totalidad para procesarlo? ¿O puede procesarlo línea por línea?

Cargar un archivo completo a la vez puede dar como resultado un rendimiento deficiente incluso para archivos que no son demasiado grandes. Su mejor opción es definir un tamaño de búfer que funcione para usted y leer / procesar los datos de un búfer a la vez.


Recomiendo aprovechar fuertemente expresiones regulares y buscar en el "nuevo" paquete IO nio para una entrada más rápida. Entonces debería ir tan rápido como puedas esperar realmente Gigabytes de datos.


Si sus datos numéricos se muestrean regularmente y necesita hacer un acceso aleatorio, considere almacenarlos en un árbol cuádruple .


Sin ninguna información adicional sobre qué tipo de procesamiento está ocurriendo, aquí hay algunos pensamientos generales de cuando hice un trabajo similar.

  1. Escriba un prototipo de su aplicación (tal vez incluso "uno para tirar") que realice una operación arbitraria en su conjunto de datos. Vea qué tan rápido va. Si lo más simple, lo más ingenuo que se puede pensar es aceptablemente rápido, ¡no se preocupe!

  2. Si el enfoque ingenuo no funciona, considere preprocesar los datos para que las ejecuciones posteriores se ejecuten en un tiempo aceptable. Mencionas tener que "saltar" en el conjunto de datos bastante. ¿Hay alguna manera de preprocesar eso? O bien, un paso de procesamiento previo puede generar aún más datos de índice de datos, que proporciona información de ubicación precisa de byte sobre secciones críticas y necesarias de su conjunto de datos. Luego, su ejecución de procesamiento principal puede utilizar esta información para ir directamente a los datos necesarios.

Entonces, para resumir, mi enfoque sería intentar algo simple en este momento y ver cómo se ve el rendimiento. Tal vez estará bien. De lo contrario, analice el procesamiento de los datos en varios pasos, guardando las operaciones más costosas para el preprocesamiento infrecuente.

No "cargue todo en la memoria". Simplemente realice los accesos a los archivos y permita que el caché de la página del disco del sistema operativo decida cuándo extraer realmente las cosas directamente de la memoria.


Es posible que desee echar un vistazo a las entradas en el Wide Finder Project (hacer una búsqueda en google de "wide finder" java ).

El Wide Finder implica leer muchas líneas en los archivos de registro, así que mira las implementaciones de Java y mira qué funcionó y qué no funcionó allí.


Esto depende mucho de los datos en el archivo. Los mainframes grandes han estado procesando datos secuencialmente durante mucho tiempo, pero normalmente no usan el acceso aleatorio para los datos. Simplemente lo colocan en una línea a la vez y procesan mucho antes de continuar.

Para el acceso aleatorio, a menudo es mejor construir objetos con envoltorios de almacenamiento en caché que saben en qué lugar del archivo se encuentran los datos que necesitan construir. Cuando es necesario, leen esos datos y se construyen solos. De esta forma, cuando la memoria es escasa, puedes comenzar a eliminar cosas sin preocuparte demasiado por no poder recuperarlas más tarde.


Si es posible, obtenga los datos en una base de datos. Luego puede aprovechar toda la indexación, almacenamiento en caché, fijación de memoria y otras funcionalidades disponibles para usted allí.


Si necesita acceder a los datos más de una vez, cárguelos en una base de datos. La mayoría de las bases de datos tienen algún tipo de utilidad de carga masiva. Si todos los datos pueden caber en la memoria, y no necesita mantenerlo ni acceder a él con tanta frecuencia, probablemente pueda escribir algo simple en Perl o en su lenguaje de scripting favorito.


Entonces, ¿qué pasa si el procesamiento requiere saltar en los datos para múltiples archivos y múltiples almacenamientos intermedios? ¿La apertura y el cierre constantes de los archivos binarios se volverán caros?

Soy un gran admirador de ''memory mapped I / o'' , también conocido como ''byte buffers directos'' . En Java se llaman Mapped Byte Buffers y forman parte de java.nio. (Básicamente, este mecanismo usa el sistema de paginación de memoria virtual del sistema operativo para ''mapear'' sus archivos y presentarlos programáticamente como búferes de bytes. El sistema operativo administrará mover los bytes a / desde el disco y la memoria de forma automática y muy rápidamente.

Sugiero este enfoque porque a) me funciona, yb) le permitirá centrarse en su algoritmo y dejar que la JVM, el sistema operativo y el hardware se encarguen de la optimización del rendimiento. Todos a menudo, saben lo que es mejor más que nosotros los humildes programadores. ;)

¿Cómo usarías los MBB en tu contexto? Simplemente crea un MBB para cada uno de tus archivos y léelos como mejor te parezca. Solo necesitará almacenar sus resultados. .

Por cierto: ¿con qué cantidad de datos está tratando, en GB? Si es más de 3-4GB, entonces esto no funcionará para usted en una máquina de 32 bits ya que la implementación de MBB está demandada en el espacio de memoria direccionable por la arquitectura de la plataforma. Una máquina y sistema operativo de 64 bits lo llevará a 1TB o 128TB de datos cartográficos.

Si está pensando en el rendimiento, entonces conozca a Kirk Pepperdine (un famoso gurú del rendimiento de Java). Está involucrado con un sitio web, www.JavaPerformanceTuning.com, que tiene algunos detalles más de MBB: NIO Performance Tips y otras cosas relacionadas con el rendimiento de Java.