Resultados de ORM Query: Arrays vs Result handle envueltos en la interfaz de Iterator

De acuerdo, aquí hay uno para los profesionales:

Desde hace un par de años, he estado trabajando en mi propia implementación PHP ORM / ActiveRecord que llamé Pork.dbObject.

Se basa libremente en la película “Haz tu propio sitio con Rails en 5 minutos” que todos vimos hace un par de años. Puedes hacer cosas como:

$clients = dbObject::Search("Client", array("ID > 500")); 

o

 $client = new Client(218); // fetch row with id 218 from client table 

o

 $projects = $client->Find('Project'); 

Esto obtendrá una o más filas de la base de datos, las envolverá en un dbObject y las devolverá en una matriz, o devolverá false de que no hay resultados.

Todo esto ha funcionado perfectamente en docenas de sitios y backends, pero ahora mi colega lo está usando para crear un enorme logparser y aquí comienza el problema de uso de memoria.

Las consultas que ejecuta pueden devolver más de 20.000 filas, tal vez incluso más, lo cual, por supuesto, no es algo muy bueno para envolver en un envoltorio de objetos de una sola vez y regresar como una única matriz.

La solución obvia sería devolver un objeto que implemente la interfaz Iterator en lugar de una matriz. No debe buscar instantáneamente todos los registros del conjunto de resultados, sino solo mantener el recurso del resultado para la consulta de la base de datos generada y usar mysql_fetch_ * internamente cuando recorra el objeto como si fuera una matriz.

Ahora llegamos a mi verdadera pregunta: ¿puedo, sin ningún problema, hacer esto? ¿Las bases de datos pueden manejar múltiples resultados abiertos, mezclarlos y mantenerlos en la memoria por un tiempo?

Por ejemplo, busque 20 objetos, bucleelos, deje que cada uno de estos 20 busque otros 5, que a su vez también busquen otros 3. Esto crearía un bucle donde se mantendrán en la memoria varios manejadores de resultados diferentes.

Sé que no puedo serializar uno de estos objetos, pero ¿podré implementar esto sin ningún problema en PHP5, o las interfaces de la base de datos me darán problemas?

Depende de qué base de datos está utilizando y la configuración de su base de datos.

Para MySQL necesita asegurarse de usar consultas almacenadas. En PDO lo configuraste así:

 $myPdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); 

Esto significa que todos los datos se enviarán al cliente (no es lo mismo que recuperarlo en PHP).

La otra alternativa (probablemente peor) es abrir una nueva conexión a la base de datos siempre que detecte una consulta que se está ejecutando con un conjunto de resultados aún abierto.

El mysql_query() normal utiliza una consulta en búfer, por lo que funcionará con múltiples conjuntos de resultados.