Utilizando fgetcsv, puede de alguna manera hacer destructiva de lectura donde las filas he leído y procesado sería descartada así que si no me lo hacen a través de todo el archivo en el primer pase, puedo regresar y recoger donde lo dejé antes de the script timed out?

Detalles Adicionales:

Me estoy haciendo un diario de alimentación de producto de un proveedor que viene a través como una de 200mb .gz archivo. Cuando me descomprimir el archivo, se convierte en un 1,5 gb .csv con casi 500.000 filas y 20 – 25 campos. Tengo que leer esta información en una base de datos MySQL, idealmente con PHP, puedo programar un CRON para que se ejecute el script en mi proveedor de hosting web cada día.

Tengo un duro tiempo de espera en el servidor establece en 180 segundos por el proveedor de hosting, y el máximo límite de utilización de la memoria de 128mb para cualquier secuencia de comandos. Estos límites no pueden ser modificadas por mí.

Mi idea era agarrar la información de la .csv usando el fgetcsv función, pero estoy esperando a tener que hacer varias pasadas en el archivo, ya que de los 3 minutos de tiempo de espera, yo estaba pensando que sería bueno para colmar en el archivo como puedo procesar de manera que no necesita gastar ciclos saltando sobre las filas que ya fueron procesados en un anterior paso.

  • Por favor enviar el código. Cualquier otra forma de asistencia en la optimización de su código es imposible.
  • Tamaño de archivo CSV?
  • No puede guardar el número de líneas que ya se analiza?
  • Una «lectura destructiva» obligaría a reescribir el archivo completo para todo lo que usted desea eliminar. Eso es prohibitivamente caro, que no lo queremos!
  • Perdóname, soy nuevo en el fgetcsv función, hay una manera para mí para pasar x filas en posteriores ejecuciones?
  • Dando el hecho de que esta función se ejecuta utilizando el mismo archivo de controlador puede utilizar otras funciones del archivo como el fseek…

InformationsquelleAutor Robert82 | 2013-10-22

3 Comentarios

  1. 14

    De la descripción del problema es realmente suena como que usted necesita para cambiar de host. Procesamiento de 2 GB de archivos con un límite de tiempo no es un ambiente constructivo. Habiendo dicho eso, la eliminación de leer las líneas del archivo es aún menos constructivas, ya que tendría que reescribir todo el de 2 GB en el disco menos la parte que ya han leído, que es muy caro.

    Suponiendo que guardar el número de filas que ya ha sido procesada, usted puede omitir filas como esta:

    $alreadyProcessed = 42; //for example
    
    $i = 0;
    while ($row = fgetcsv($fileHandle)) {
        if ($i++ < $alreadyProcessed) {
            continue;
        }
    
        ...
    }

    Sin embargo, esto significa que usted está leyendo el entero 2 GB de archivos desde el principio cada vez que usted vaya a través de él, que en sí mismo ya lleva un tiempo y usted será capaz de procesar menos y menos filas cada vez que inicie de nuevo.

    La mejor solución aquí es recordar que el posición actual del puntero de fichero, para que ftell es la función que estás buscando:

    $lastPosition = file_get_contents('last_position.txt');
    $fh = fopen('my.csv', 'r');
    fseek($fh, $lastPosition);
    
    while ($row = fgetcsv($fh)) {
        ...
    
        file_put_contents('last_position.txt', ftell($fh));
    }

    Esto le permite volver a la última posición en que estaban y seguir leyendo. Obviamente usted quiere añadir un montón de errores de manejo aquí, así que usted nunca está en un estado incoherente no importa en qué punto de su secuencia de comandos se interrumpe a.

    • Gran solución, muy cuidada y elegante. Me consiguió a través de esta crisis.
    • Me salvó durante un hack day. Gracias.
  2. 1

    Puede evitar el tiempo de espera y un error de memoria, en cierta medida cuando la lectura como un Torrente. Leyendo línea por línea y, a continuación, inserta cada línea en una base de datos (O Proceso en consecuencia). De esa manera sólo de una sola línea se mantenga en la memoria en cada iteración. Por favor nota: no intente cargar una enorme csv-archivo en una matriz, que realmente consumen una gran cantidad de memoria.

    if(($handle = fopen("yourHugeCSV.csv", 'r')) !== false)
    {
        //Get the first row (Header)
        $header = fgetcsv($handle);
    
        //loop through the file line-by-line
        while(($data = fgetcsv($handle)) !== false)
        {
            //Process Your Data
            unset($data);
        }
        fclose($handle);
    }
    • Esto es similar a lo que yo estaba pensando, pero con 3 minutos de tiempo de espera, yo no espero ser capaz de leer el archivo completo en un solo paso. Es allí una manera de volver en un segundo paso, y acaba de «saltar» a una fila en particular? Dicen que puedo obtener de 125.000 filas de hecho la primera vez, puedo empezar en la fila 125,001 el segundo tiempo a través de?
  3. 0

    Creo que una solución mejor (será phenomnally ineficiente continuamente rebobinar y escribir para abrir el archivo stream) sería para el seguimiento de la posición del archivo de cada registro leído (utilizando ftell) y guárdela con los datos que he leído – a continuación, si usted tiene que resume, a continuación, sólo el fseek a la última posición.

    Usted podría tratar de cargar el archivo directamente mediante el uso de mysql leer el archivo de función (que probablemente será mucho más rápido), aunque he tenido problemas con esto en el pasado y terminé de escribir mi propio código php.

    Tengo un duro tiempo de espera en el servidor establece en 180 segundos por el proveedor de hosting, y el máximo límite de utilización de la memoria de 128mb para cualquier secuencia de comandos. Estos límites no pueden ser modificadas por mí.

    Lo has intentado?

    La memoria puede estar limitado por otros medios que no sean el de php.archivo ini, pero no puedo imaginar cómo alguien en realidad podría impedir el uso de un diferente tiempo de ejecución (incluso si ini_set está deshabilitado, desde la línea de comandos puede ejecutar php -d max_execution_time=3000 /your/script.php o php -c /ruta/a/custom/inifile /your/script.php )

    A menos que usted está tratando de ajustarse a la totalidad del fichero de datos en la memoria, entonces no debería haber ningún problema con un límite de memoria de 128 mb

Dejar respuesta

Please enter your comment!
Please enter your name here