es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Automatizando la extracción de datos de un gran archivo JSON (~8GB)

Tengo un archivo JSON bastante grande (~8GB) que tiene el siguiente formato:

{
    // algunos campos fijos
    "data": [
        {
            // campos no importantes
            "importantField": "una cadena alfanumérica"
        },
        {
            // mismo formato que el anterior
        },
        ...
    ]
}

Quiero extraer todos los valores del campo importantField en un archivo separado y quiero hacerlo automáticamente.

Intenté usar este comando grep:

grep -E -o '"importantField":"[[:alnum:]]+"' file.json

pero el proceso se detuvo debido al uso de memoria grande (usó más del 80% de mi RAM en algunos puntos y la interfaz gráfica no respondía).

Luego intenté primero usar el comando split para separar la entrada en archivos de 2GB:

split --bytes 2000000000 file.json out_

y luego usar el mismo comando grep de arriba, y esta vez terminó rápidamente para cada fragmento, en unos 30 segundos.

Este método en el que tengo que dividir primero la entrada estaría bien para mí, pero el único problema es verificar automáticamente si el comando split divide correctamente el archivo, es decir, no en medio del par clave-valor de importantField, ya que eso resultaría en la pérdida de datos importantes.

Me gustaría saber si hay una forma mejor/más elegante de hacer esto.

También me interesa saber por qué el comando grep no funciona en un archivo de 8GB, pero funciona perfectamente en archivos de 2GB. La expresión regular que uso para hacer la coincidencia no parece ser mala.

Mi suposición es que intenta cargar toda la línea primero (lo cual utiliza la mitad de mi RAM) y luego usa más memoria para sus cálculos internos, lo que hace que el sistema comience a usar la memoria SWAP, lo que a su vez provoca un rendimiento realmente lento antes de terminar el programa (10+ minutos).

Algunos datos importantes específicos para este problema:
– El formato de los objetos dentro del array data siempre será el mismo.
– El archivo JSON de entrada está minificado, no contiene espacios ni nuevas líneas.
– El archivo de entrada es estático.
– Obviamente, estoy interesado en extraer todos los datos importantes.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Extracción de valores importantes de un archivo JSON grande

    Como experto en TI especializado en JSON, bash y archivos grandes, necesitamos extraer todos los valores de importantField de un archivo JSON de 8GB en un archivo separado de manera automática.

    Solución

    Podemos dividir el archivo JSON de entrada en varios archivos utilizando el comando split y luego utilizar grep para extraer los valores de importantField de cada archivo. Luego podemos unir los resultados utilizando el comando cat y guardarlos en un archivo separado.

    Pasos

    1. Dividir el archivo de entrada en archivos de 2GB utilizando el comando split de la siguiente manera:
    $ split --bytes 2000000000 file.json out_
    

    Esto dividirá el archivo de entrada en varios archivos con nombres que comienzan con out_.

    1. Utilizar grep para extraer los valores de importantField de cada archivo de la siguiente manera:
    $ grep -o '"importantField":"[[:alnum:]]\+"' out_* > important_fields.txt
    

    Esto extraerá todos los valores de importantField de cada archivo dividido y los guardará en un archivo separado llamado important_fields.txt.

    1. Unir los resultados utilizando el comando cat y guardarlos en un archivo separado de la siguiente manera:
    $ cat important_fields.txt > all_important_fields.txt
    

    Esto concatenará todos los valores de importantField en un solo archivo llamado all_important_fields.txt.

    Verificación de la división adecuada de los archivos

    Necesitamos asegurarnos de que el comando split no divida el archivo de entrada en medio del par clave-valor importantField. Esto se puede hacer ejecutando el comando grep en los archivos divididos y comprobando si algún par importantField está dividido entre dos archivos.

    $ grep -c '"importantField"' out_*
    

    Esto mostrará el número de ocurrencias de importantField en cada archivo dividido. Luego podemos verificar manualmente si alguna ocurrencia está dividida entre dos archivos.

    Problemas de rendimiento con el comando grep

    El comando grep tuvo problemas de rendimiento al ejecutarse en un archivo de 8GB. Esto se debió al gran uso de memoria que requería. Al ejecutarse en archivos de 2GB, terminó bastante rápido en unos 30 segundos. Esto se debe posiblemente al hecho de que grep primero carga toda la línea en memoria, lo cual utiliza la mitad de la RAM, y luego utiliza más memoria para sus cálculos internos, lo que hace que el sistema comience a utilizar la memoria SWAP, lo que a su vez causa un rendimiento lento antes de terminar el programa.

    Conclusión

    Para extraer los valores de importantField de un archivo JSON grande, podemos dividir el archivo en varios archivos, extraer los valores de cada archivo dividido y unirlos en un solo archivo. También debemos asegurarnos de que la división se realice correctamente. El comando grep puede tener problemas de rendimiento al trabajar con archivos grandes.

Comments are closed.