Symfony2 / Doctrine hace que la declaración $-> execute () no “almacene” todos los valores

Tengo un conjunto de códigos básico como este (dentro de un controlador):

$sql = 'select * from someLargeTable limit 1000';
$em = $this->getDoctrine()->getManager();
$conn = $em->getConnection();
$statement = $conn->prepare($sql);
$statement->execute();

Mi dificultad es que cuando el conjunto de resultados son solo unos pocos registros, el uso de la memoria no es tan malo. Me hice eco de alguna información de depuración antes y después de ejecutar la instrucción $- > execute (); parte del código, y descubrí para mi implementación que tengo lo siguiente:

pre-execute... rowCount :: 0 memory: 49.614 MB
post-execute... rowCount :: 1000 memory: 50.917 MB

Al subir esto de 1000 registros, a 10k, la diferencia en el uso de MB aumenta a 13 MB

pre-execute... rowCount :: 0 memory: 49.614 MB
post-execute... rowCount :: 10000 memory: 62.521 MB

Finalmente, recuperando alrededor de 50k registros me acerco a mi asignación máxima de memoria:

pre-execute... rowCount :: 0 memory: 49.614 MB
post-execute... rowCount :: 50000 memory: 114.096 MB

Con esta implementación, no hay forma de que pueda escribir un controlador (o incluso un comando para el caso) que me permita recuperar un CSV de datos. Claro, 50k entradas suenan mucho y la pregunta plantea por qué, pero ese no es el problema.

Mi última pregunta es: ¿Es posible decirle a DBAL / Connection o DBAL / Statement que, al ejecutar, almacene los datos dentro de SQL en lugar de en PHP en su totalidad. Por ejemplo, si tengo 10 millones de filas, para enviar solo las primeras 10k filas a PHP … déjenme revisarlas a través de @ instrucción- > fetch (); y cuando el cursor llega al final de los 10k, truncar la matriz y obtener los próximos 10k de la base de datos?

Mejor respuesta
NOTA: esta respuesta es incorrecta. He intentado eliminarlo, pero no desaparecerá, porque es el aceptado. Lo marqué para revisión de mod, pero no lo eliminarán. Vea las otras respuestas para mejores soluciones. – lxg

Suponiendo que su consulta se pueda representar en DQL, puede usar una consulta iterada con DQL:

$i = 0;
$batchSize = 100; // try different values, like 20 <= $batchSize <= 1000
$q = $em->createQuery('SELECT e FROM YourWhateverBundle:Entity');
$iterableResult = $q->iterate();

foreach($iterableResult as $row)
{
    $entity = $row[0];

    // do whatever you need with the entity object

    if (($i % $batchSize) == 0)
    {
        $em->flush(); // if you need to update something
        $em->clear(); // frees memory. BEWARE: former entity references are lost.
    }
    ++$i;

    // if you only want to process a certain number of elements,
    // you can of course break the loop here.
}

http://docs.doctrine-project.org/en/2.0.x/reference/batch-processing.html

Si necesita utilizar una consulta nativa, puede trabajar con las compensaciones de LIMIT para generar fragmentos de 1000 registros e intentar borrar el EntityManager entre ellos. (No he probado esto, pero de todos modos evitaría consultas nativas con Doctrine).

Por favor indique la dirección original:Symfony2 / Doctrine hace que la declaración $-> execute () no “almacene” todos los valores - Código de registro