Saltar al contenido

¿Cuál es la diferencia entre el cursor de laravel y el método de fragmento de laravel?

Este team de expertos luego de algunos días de investigación y de recopilar de información, encontramos los datos necesarios, esperamos que te sea útil en tu trabajo.

Solución:

Tenemos una comparativa: fragmento () vs cursor ()

  • cursor (): alta velocidad
  • chunk (): Uso constante de memoria

10,000 registros:

+-------------+-----------+------------+
|             | Time(sec) | Memory(MB) |
+-------------+-----------+------------+
| get()       |      0.17 |         22 |
| chunk(100)  |      0.38 |         10 |
| chunk(1000) |      0.17 |         12 |
| cursor()    |      0.16 |         14 |
+-------------+-----------+------------+

100,000 registros:

+--------------+------------+------------+
|              | Time(sec)  | Memory(MB) |
+--------------+------------+------------+
| get()        |        0.8 |     132    |
| chunk(100)   |       19.9 |      10    |
| chunk(1000)  |        2.3 |      12    |
| chunk(10000) |        1.1 |      34    |
| cursor()     |        0.5 |      45    |
+--------------+------------+------------+
  • TestData: tabla de usuarios de la migración predeterminada de Laravel
  • Homestead 0.5.0
  • PHP 7.0.12
  • MySQL 5.7.16
  • Laravel 5.3.22

De hecho, esta pregunta podría atraer alguna respuesta obstinada, sin embargo, la respuesta simple está aquí en Laravel Docs

Solo para referencia:

Este es un trozo:

Si necesita procesar miles de registros de Eloquent, utilice el chunk mando. los chunk El método recuperará un “trozo” de modelos Eloquent, alimentándolos a un determinado Closure para procesar. Utilizando el chunk El método conservará memoria cuando se trabaja con conjuntos de resultados grandes:

Este es el cursor:

los cursor El método le permite iterar a través de los registros de su base de datos usando un cursor, que solo ejecutará una única consulta. Al procesar grandes cantidades de datos, el cursor El método se puede utilizar para reducir en gran medida el uso de la memoria:

Chunk recupera los registros de la base de datos y los carga en la memoria mientras coloca un cursor en el último registro recuperado para que no haya conflictos.

Entonces, la ventaja aquí es que si desea reformatear el grande grabar antes de que se envíen, o si desea realizar una operación en una enésima cantidad de registros por vez, esto es útil. Un ejemplo es si está construyendo una hoja de vista / excel, por lo que puede tomar el registro en recuentos hasta que estén listos para que no todos se carguen en la memoria a la vez y, por lo tanto, alcancen el límite de memoria.

El cursor usa generadores PHP, puede consultar la página de generadores php, sin embargo, aquí hay un título interesante:

Un generador le permite escribir código que usa foreach para iterar sobre un conjunto de datos sin necesidad de construir un array en la memoria, lo que puede hacer que exceda un límite de memoria o que requiera una cantidad considerable de tiempo de procesamiento para generar. En su lugar, puede escribir una función de generador, que es lo mismo que una función normal, excepto que en lugar de regresar una vez, un generador puede rendir tantas veces como sea necesario para proporcionar los valores sobre los que se iterará.

Si bien no puedo garantizar que entiendo completamente el concepto de Cursor, para Chunk, chunk ejecuta la consulta en cada tamaño de registro, recuperándola y pasándola al cierre para trabajos posteriores en los registros.

Espero que esto sea útil.

Cursor()

  • solo una consulta
  • buscar resultado por llamada PDOStatement::fetch()
  • de forma predeterminada, se utiliza una consulta almacenada en búfer y se obtienen todos los resultados a la vez.
  • convirtió solo la fila actual en un modelo elocuente

Pros

  • minimizar la sobrecarga de memoria del modelo elocuente
  • fácil de manipular

Contras

  • grandes oportunidades de resultados a sin memoria
  • con o sin búfer es una compensación

Chunk()

  • fragmentar la consulta en consultas con límite y compensación
  • buscar resultado por llamada PDOStatement::fetchAll
  • convirtió los resultados en modelos elocuentes por lotes

Pros

  • tamaño de memoria usada controlable

Contras

  • convertir los resultados en modelos elocuentes por lotes puede causar cierta sobrecarga de memoria
  • las consultas y el uso de la memoria es un traid-off

TL; DR

solía pensar cursor() Hará consultas cada vez y solo mantendrá el resultado de una fila en la memoria. Entonces, cuando vi la tabla de comparación de @mohammad-asghari, me confundí mucho. Debe ser algo buffer entre bastidores.

Rastreando el código de Laravel como se muestra a continuación

/**
 * Run a select statement against the database and returns a generator.
 *
 * @param  string  $query
 * @param  array  $bindings
 * @param  bool  $useReadPdo
 * @return Generator
 */
public function cursor($query, $bindings = [], $useReadPdo = true)

    $statement = $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) 
        if ($this->pretending()) 
            return [];
        

        // First we will create a statement for the query. Then, we will set the fetch
        // mode and prepare the bindings for the query. Once that's done we will be
        // ready to execute the query against the database and return the cursor.
        $statement = $this->prepared($this->getPdoForSelect($useReadPdo)
                          ->prepare($query));

        $this->bindValues(
            $statement, $this->prepareBindings($bindings)
        );

        // Next, we'll execute the query against the database and return the statement
        // so we can return the cursor. The cursor will use a PHP generator to give
        // back one row at a time without using a bunch of memory to render them.
        $statement->execute();

        return $statement;
    );

    while ($record = $statement->fetch()) 
        yield $record;
    

Entendí que Laravel construye esta característica por envoltura PDOStatement :: fetch (). Y por busqueda recuperación de PDO de búfer y MySQL, Encontré este documento.

https://www.php.net/manual/en/mysqlinfo.concepts.buffering.php

Las consultas utilizan el modo de búfer de forma predeterminada. Esto significa que los resultados de la consulta se transfieren inmediatamente desde el servidor MySQL a PHP y luego se guardan en la memoria del proceso PHP.

así que al hacer PDOStatement :: execute () en realidad obtenemos filas de resultados completas en unos y almacenado en la memoria, no solo una fila. Entonces, si el resultado es demasiado grande, esto conducir a la memoria excepción.

Aunque el Documento mostrado, podríamos usar $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); para deshacerse de la consulta almacenada en búfer. Pero el inconveniente debería ser la precaución.

Las consultas MySQL sin búfer ejecutan la consulta y luego devuelven un recurso mientras los datos todavía están esperando en el servidor MySQL para ser recuperados. Esto usa menos memoria en el lado de PHP, pero puede aumentar la carga en el servidor. A menos que el conjunto de resultados completo se haya obtenido del servidor, no se pueden enviar más consultas a través de la misma conexión. Las consultas sin búfer también se pueden denominar “resultado de uso”.

Acuérdate de que tienes la capacidad de agregar una reseña si diste con el arreglo.

¡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 *