Saltar al contenido

Leyendo grandes matrices desde un archivo json grande en php

Encontramos el hallazgo a este asunto, o por lo menos eso esperamos. Si continuas con inquietudes coméntalo y sin tardar

Solución:

JSON es un gran formato y una alternativa mucho mejor a XML. Al final, JSON es casi uno a uno convertible a XML y viceversa.

Los archivos grandes pueden aumentar de tamaño, por lo que no queremos leer todo el contenido de la memoria y no queremos analizar todo el archivo. Tuve el mismo problema con los archivos JSON de tamaño XXL.

Creo que el problema no radica en un lenguaje de programación específico, sino en una realización y especificidad de los formatos.

Tengo 3 soluciones para ti:

  1. Implementación nativa de PHP (privilegiado)

Casi tan rápido como XMLReader transmitido, hay una biblioteca https://github.com/pcrov/JsonReader. Ejemplo:

use pcrovJsonReaderJsonReader;

$reader = new JsonReader();
$reader->open("data.json");

while ($reader->read("type")) 
    echo $reader->value(), "n";

$reader->close();

Esta biblioteca no leerá todo el archivo en la memoria ni analizará todas las líneas. Es paso a paso el comando atravesar el árbol del objeto JSON.

  1. Dejar ir formatos (contras: múltiples conversiones)

Procesar previamente el archivo a un formato diferente como XML o CSV. Hay bibliotecas de nodejs muy ligeras como https://www.npmjs.com/package/json2csv a CSV desde JSON.

  1. Use alguna base de datos NoSQL (contras: software complejo adicional para instalar y mantener)

Por ejemplo, Redis o CouchDB (importar archivo json a couch db-)

Su problema está básicamente relacionado con la gestión de la memoria realizada por cada lenguaje de programación específico que podría utilizar para acceder a los datos desde un archivo enorme (con fines de almacenamiento).

Por ejemplo, cuando acumula las operaciones utilizando el código que acaba de mencionar (como se muestra a continuación)

$data = json_decode(file_get_contents(storage_path("test/ts/ts_big_data.json")), true);

lo que sucede es que la memoria utilizada por el motor Zend en tiempo de ejecución aumenta demasiado, porque tiene que asignar ciertas unidades de memoria para almacenar referencias sobre cada manejo de archivos en curso involucrado en su declaración de código, como mantener también en la memoria un puntero, no solo el archivo real abierto – a menos que este archivo finalmente se sobrescriba y el búfer de memoria se libere (libere) nuevamente. No es de extrañar que si fuerza la ejecución de ambos file_get_contents () función que lee el archivo en una string y tambien el json_decode () función, obliga al intérprete a mantener en memoria las 3 “cosas”: el archivo en sí, la referencia creada (el string), y también la estructura (el archivo json).

Por el contrario, si divide la declaración en varias, la pila de memoria retenida por la primera estructura de datos (el archivo) se descargará cuando la operación de “obtener su contenido” y luego escribirla en otra variable (o archivo) se realice por completo. . Siempre que no defina una variable donde guardar los datos, aún permanecerá en la memoria (como un blob – con sin nombre, sin dirección de almacenamiento, solo contenido). Por esta razón, es mucho más efectivo en CPU y RAM, cuando se trabaja con big data, dividir todo en pasos más pequeños.

Entonces, primero debe comenzar simplemente reescribiendo su código de la siguiente manera:

$somefile = file_get_contents(storage_path("test/ts/ts_big_data.json"));

$data = json_decode($somefile, true);

Cuando se ejecuta la primera línea, la memoria se mantiene por ts_big_data.json se libera (considérelo como purgado y puesto a disposición de nuevo para otros procesos).

Cuando se ejecuta la segunda línea, también $ somefileEl búfer de memoria también se libera. El punto clave de esto es que en lugar de tener siempre 3 búferes de memoria usados ​​solo para almacenar las estructuras de datos, solo tendrá 2 en cada momento, si por supuesto ignora la otra memoria usada para construir el archivo. Por no decir que cuando se trabaja con matrices (y los archivos JSON son exactamente matrices), esa memoria asignada dinámicamente aumenta drásticamente y no es lineal, como tendemos a pensar. La conclusión es que en lugar de una pérdida del 50% en el rendimiento solo en la asignación de almacenamiento para los archivos (3 archivos grandes que ocupan un 50% más de espacio que solo 2 de ellos), logramos manejar mejor en pasos más pequeños la ejecución de las funciones. ‘estos archivos enormes.

Para entender esto, imagina que accedes solo a lo que necesitas en un momento determinado (este también es un principio llamado YAGNI -No lo vas a necesitar, o similar en el contexto de Prácticas de programación extremas), consulta la referencia aquí. https://wiki.c2.com/?YouArentGonnaNeedIt algo heredado desde los viejos tiempos de C o Cobol.

El siguiente enfoque a seguir es dividir el archivo en más partes, pero en una estructurada (estructura de datos dependiente relacional) como en una tabla / tablas de base de datos.

Obviamente, debe guardar los datos nuevamente como manchas, en la base de datos. La ventaja es que la recuperación de datos en una base de datos es mucho más rápida que en un archivo (debido a la asignación de índices por parte del SQL al generar y actualizar las tablas). Se puede acceder a una tabla que tiene 1 o dos índices de una manera increíblemente rápida mediante una consulta estructurada. Nuevamente, los índices apuntan al almacenamiento principal de los datos.

Sin embargo, un tema importante es que si aún desea trabajar con json (contenido y tipo de almacenamiento de datos, en lugar de tablas en una base de datos) es que no puede actualizarlo localmente sin cambiarlo globalmente. No estoy seguro de lo que quiso decir al leer los valores de la función relacionada con el tiempo en el archivo json. ¿Quiere decir que su archivo json cambia continuamente? Es mejor dividirlo en varias tablas para que cada una pueda cambiar sin afectar toda la megaestructura de los datos. Más fácil de administrar, más fácil de mantener, más fácil de localizar los cambios.

Tengo entendido que la mejor solución sería dividir el mismo archivo en varios archivos json donde elimine los valores no necesarios. A propósito, ¿REALMENTE NECESITA TODOS LOS DATOS ALMACENADOS?

No vendría ahora con un código a menos que me explique los problemas anteriores (para que podamos tener una conversación) y, a partir de entonces, editaré mi respuesta en consecuencia. Ayer escribí una pregunta relacionada con el manejo de blobs y el almacenamiento en el servidor para acelerar la ejecución de una actualización de datos en un servidor mediante un proceso cron. Mis datos eran de aproximadamente 25 MB + no 500+ como en su caso, sin embargo, debo entender el caso de uso para su situación.

Una cosa más, ¿cómo se creó ese archivo que debes procesar? ¿Por qué administra solo la forma final en lugar de intervenir para alimentarlo con datos? Mi opinión es que puede dejar de almacenar datos en él como se hizo anteriormente (y por lo tanto dejar de aumentar su dolor) y, en cambio, transformar su propósito actual solo en almacenamiento de datos históricos de ahora en adelante y luego pasar a almacenar los datos futuros en algo más elástico (como Bases de datos MongoDB o NoSQL).

Probablemente no necesite tanto un código como una estrategia sólida y útil y una forma de trabajar con sus datos primero.

La programación viene en último lugar, después de que hayas decidido toda la arquitectura detallada de tu proyecto web.

Si para ti ha resultado de utilidad nuestro artículo, sería de mucha ayuda si lo compartieras con otros seniors de esta forma contrubuyes a difundir nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *