Problema al intentar obtener una cantidad muy grande de datos.

6,707 views
Skip to first unread message

Gabriel Divenuto

unread,
Jan 26, 2011, 12:00:43 PM1/26/11
to php...@googlegroups.com
Buenas tardes,
necesito traer 55,695 filas al ejecutar una query con PHP, el código con el cual estoy probando es el siguiente:

<?php
//ini_set("memory_limit",'256M');

//SE ABRE LA CONEXION
$conexion = mysql_connect($servidor, $usuario, $password, true, 65536)
or die ("Falló la conexión al Servidor <br>Error: ".mysql_error()."<br>\n");
       
mysql_select_db($base_datos, $conexion) or die("Falló la selección de la Base de Datos <br>Error: ".mysql_error()."<br>\n");

// QUERY DE EJEMPLO, LA REAL DEVUELVE 55,695 FILAS
$sql = "SELECT campo1, campo2, campo3, campo4, campo5, campo6, campo7
    FROM tabla_ejemplo
    WHERE fecha BETWEEN '1983-01-01' AND '2011-01-20'
    ";

// SE UTILIZA PARA IR UNIENDO LOS DATOS DEVUELTOS EN CADA CICLO
$listado_para_reporte = Array();

// SE INICIALIZA EL INICIO Y EL RANGO DEL LIMITE A PEDIR
$inicio = 0;   
$rango = 500;
do {
    // SE DEFINE EL LIMITE PARA LA QUERY
    $limite_para_documento = " LIMIT ".$inicio.", ".$rango."";

    // SE INICIALIZA CON LA QUERY SIN EL LIMITE, PARA AGREGARSELO MODIFICADO EN CADA CICLO
    $sql_parcial = $sql;

    // SE AGREGA EL LIMITE A LA QUERY PARCIAL
    $sql_parcial .= $limite_para_documento;
    //fputs(fopen('sql_auxiliar_'.$r.'_armar_listado_para_reporte.txt', 'w'), print_r($sql_parcial, true));
   
    // SE EJECUTA LA QUERY PARCIAL    
    $resultado_parcial = mysql_query($sql_parcial);

    $total_devueltos = mysql_num_rows($resultado_parcial);
    // SI DEVUELVE ALGUN REGISTRO
    if ($total_devueltos != 0) {

    // SE UTILIZA UN VECTOR AUXILIAR
    $i=0;
    while ($row = mysql_fetch_array($resultado_parcial, MYSQL_ASSOC)) {
        $vector_auxiliar[$i] = $row;
        $i++;
    }
    //fputs(fopen('vector_auxiliar_'.$r.'_armar_listado_para_reporte_M.txt', 'w'), print_r($vector_auxiliar, true));
       
    // SE LIBERA LA MEMORIA USADA POR LA QUERY PARCIAL
    mysql_free_result($resultado_parcial);

    // SE VA ARMANDO EL LISTADO A MEDIDA QUE SE OBTIENEN LOS DATOS
    $listado_para_reporte = array_merge($listado_para_reporte, $vector_auxiliar);
    //fputs(fopen('LISTADO_REPORTE_AUX_'.$inicio.'__armar_listado_para_reporte.txt', 'w'),print_r($listado_para_reporte, true));
    }
    // SE SIGUE CON LOS SIGUIENTES 500 REGISTROS (EN CASO DE EXISTIR)
    $inicio += $rango;

} while ($total_devueltos == $rango);// CUANDO SE OBTENGAN MENOS DEL RANGO YA NO HACE FALTA SEGUIR

// SE CIERRA LA CONEXION
mysql_close($conexion);

//fputs(fopen('LISTADO_COMPLETO_testear_otra_manera_sp.txt', 'w'),print_r($listado_para_reporte, true));
$cantidad = count($listado_para_reporte);
for ($f=0; $f < $cantidad; $f++){
    $fila = &$listado_para_reporte[$f];

    echo 'Campo 1: '.$fila['campo1'].'<br>';
    echo 'Campo 2: '.$fila['campo2'].'<br>';
    echo 'Campo 3: '.$fila['campo3'].'<br>';
    echo 'Campo 4: '.$fila['campo4'].'<br>';
    echo 'Campo 5: '.$fila['campo5'].'<br>';
    echo 'Campo 6: '.$fila['campo6'].'<br>';
    echo 'Campo 7: '.$fila['campo7'].'<br>';
  
    echo '<hr>';
}

?>

Ejecuto la query con un límite que se va modificando dentro de un do while (con un rango de 500 registros), al ejecutar el script luego de un tiempo indica que llegó al límite de memoria asignada en el servidor, he modificado al principio del script la cantidad de memoria hasta 256M y aún no alcanza.

Si ejecuto la query desde phpmyadmin me devuelve todas las filas sin problemas y bastante rápido, por eso he probado con un procedimiento almacenado en MySQL, al ejecutarlo con PHP también surge el mismo problema.

Quisiera saber si han necesitado traer una cantidad muy grande de filas y les ha pasado lo mismo, y si lo han podido solucionar.

Muchas gracias.



--
Gabriel E. Divenuto
Técnico Superior en Sistemas Informáticos
SistemasGD :: Desarrollo de Sistemas Informáticos
Mar del Plata - Argentina
Email: gabriel...@sistemasgd.com.ar
Web:
www.sistemasgd.com

Federico

unread,
Jan 26, 2011, 12:13:37 PM1/26/11
to php...@googlegroups.com
Mmm....me parece que lo que esta mal es el do while.
Me parece que estas ejecutando la query 500 veces.

2011/1/26 Gabriel Divenuto <gabriel...@gmail.com>:

> --
> Has recibido este mensaje porque estás suscrito al grupo "Grupo PHP
> Argentina" de Grupos de Google.
> Para publicar una entrada en este grupo, envía un correo electrónico a
> php...@googlegroups.com.
> Para anular tu suscripción a este grupo, envía un correo electrónico a
> php-arg+u...@googlegroups.com
> Para tener acceso a más opciones, visita el grupo en
> http://groups.google.com/group/php-arg?hl=es.
>

Federico

unread,
Jan 26, 2011, 12:18:56 PM1/26/11
to php...@googlegroups.com
Perdon. Ahora entiendo lo que queres hacer.

Proba haciendo una sola query que traiga todos los resultados.

Tambien tene en cuenta que phpmyadmin te pagina los resultados, osea
que no te trae los 56k registros sino que te trae solo ~50 o algo asi.

2011/1/26 Federico <fede...@gmail.com>:

Gabriel Divenuto

unread,
Jan 26, 2011, 12:44:13 PM1/26/11
to php...@googlegroups.com
Probé la query entera sin el LIMIT, pero no alcanza la memoria para procesar el script, lo ideal sería que devuelva la cantidad total sin agrandar dicho tamaño, probé con 256M pero tampoco alcanza.

phpmyadmin pagina el resultado mostrando de a 30 filas, o sea no devuelve todo de una.

Siempre paginé para obtener la cantidad x de resultados, pero esta vez debo armar un informe según un criterio de búsqueda, el cual es común que sea por ejemplo de un rango muy grande de fechas.

Intenté con este código ir armando un array, paginando de a poco hasta llegar a tener todas las filas pretendidas, pero PHP siempre te limita con el tamaño de la memoria.

Te agradezco un montón Federico.

Sigo probando...

Federico

unread,
Jan 26, 2011, 1:01:01 PM1/26/11
to php...@googlegroups.com
Tenes creados indices en los campos que usas en el where?

Lo que podes hacer es ir probando hasta cuantos podes traer cambiando el LIMIT.
Asi podes ir viendo cual es tu limite segun la memoria que asignas.


2011/1/26 Gabriel Divenuto <gabriel...@gmail.com>:

Guillermo Eduardo Fekete

unread,
Jan 26, 2011, 12:57:33 PM1/26/11
to php...@googlegroups.com
Hola Gabriel:
Te quería preguntar 2 cosas:

¿Ir obteniendo de a 500 registros es para ir liberando memoría?
porque, al fin y al cabo, luego del "do/while" habrás siempre obtenido
todos los registros, como si no hubieras usado el LIMIT. Si es así,
probaste obtener de a 1000 (o más), a fin de hacer menos consultas.
¿probaste hacer una sola consulta (es decir no usar limit)?

Por otra parte: ¿el que se queda sin memoría seguro que es php?¿o
puede ser el mysql? ¿podrías transcribir el error que muestra?

saludos

guillermo

Jonathan Muszkat

unread,
Jan 26, 2011, 12:53:11 PM1/26/11
to php...@googlegroups.com
Para que necesitas traer tantas filas?
Es muy raro el caso que necesites tantas filas de una.

2011/1/26 Gabriel Divenuto <gabriel...@gmail.com>
--
Has recibido este mensaje porque estás suscrito al grupo "Grupo PHP Argentina" de Grupos de Google.
Para publicar una entrada en este grupo, envía un correo electrónico a php...@googlegroups.com.
Para anular tu suscripción a este grupo, envía un correo electrónico a php-arg+u...@googlegroups.com
Para tener acceso a más opciones, visita el grupo en http://groups.google.com/group/php-arg?hl=es.



--
Jonathan Ariel Muszkat
Mail/Gtalk: mus...@gmail.com
Móvil: (011)15-4-399-6363
Linkedin: http://www.linkedin.com/in/musky
About.me: http://about.me/jonymusky
Twitter: @jonymusky
Blog: http://www.jonymusky.com.ar

Skype: jony.musky

The only way to do great work is to love what you do. If you haven’t found it yet, keep looking. -- Steve Jobs

Tordek

unread,
Jan 26, 2011, 1:14:21 PM1/26/11
to php...@googlegroups.com
2011/1/26 Gabriel Divenuto <gabriel...@gmail.com>:

> Buenas tardes,
> necesito traer 55,695 filas al ejecutar una query con PHP, el código con el
> cual estoy probando es el siguiente:

Como dice Guillermo, al hacer las consultas de a 500 y hacer un merge,
estás en la misma: Metés todos los registros en memoria a la vez.
Hacelo en una sola query.

Por otro lado, a menos que estés haciendo algun procesamiento con
todos los valores a la vez, podés imprimirlos y descartarlos apenas
los usás:

<?php
//ini_set("memory_limit",'256M');

//SE ABRE LA CONEXION
$conexion = mysql_connect($servidor, $usuario, $password, true, 65536)
or die ("Falló la conexión al Servidor <br>Error: ".mysql_error()."<br>\n");

mysql_select_db($base_datos, $conexion) or die("Falló la selección de
la Base de Datos <br>Error: ".mysql_error()."<br>\n");

// QUERY DE EJEMPLO, LA REAL DEVUELVE 55,695 FILAS
$sql = "SELECT campo1, campo2, campo3, campo4, campo5, campo6, campo7
FROM tabla_ejemplo
WHERE fecha BETWEEN '1983-01-01' AND '2011-01-20'
";

$resultado = mysql_query($sql);

while ($fila = mysql_fetch_array($resultado, MYSQL_ASSOC)) {

llarensj

unread,
Jan 26, 2011, 5:14:18 PM1/26/11
to Grupo PHP Argentina
Me parece que el problema es el array, crece demasiado. Yo por lo
general hago algo parecido a lo que esta en lineas comentadas, voy
generando un archivo intermedio, o directamente el archivo definitivo,
si es por ejemplo un excel/dbf/ancho fijo. Siempre ejecuto una query
para obtener el total de registros, y hasta ahora no tuve problemas
con un maximo histórico de 60000 registros de una query con
bastaaaantes columnas.

Algo asi, suponiendo que el destino sea un archivo txt:

$nHandle = fopen('/tmp/somefile.txt', 'w');
while ($row = mysql_fetch_array($sqlResult, MYSQL_ASSOC)) {
fwrite($nHandle, implode("\t", $row) . "\n"); //o grabacion de una
linea de un XLS o de un registro DBF etc
}
fclose($nHandle);
> //fputs(fopen('LISTADO_REPORTE_AUX_'.$inicio.'__armar_listado_para_reporte. txt',
> Email: gabrieldiven...@sistemasgd.com.ar<http://sistemasgd.com:2084/squirrelmail/src/compose.php? send_to=gabrieldiven...@sistemasgd.com.ar>
> Web:www.sistemasgd.com

Gabriel Divenuto

unread,
Jan 27, 2011, 7:08:35 AM1/27/11
to php...@googlegroups.com
Buen día,
MUCHAS GRACIAS por responder y ayudarme.

Siempre he paginado para mostrar resultados o preparar informes en formato .xls o pdf.

Pero esta vez debo terminar un reporte, para impresión, con todo el resultado consultado.

Intenté ejecutar la query sin el LIMIT e ir almacenando su resultado en un array, para utilizarlo luego en dicho informe, donde surgía:
         Fatal error: Allowed memory size of ...

Modifiquè el límite de memoria con:
         ini_set("memory_limit",'256M');  
pero seguía igual.

 Luego probé realizando lo mismo pero limitando la query, cada 500 filas para empezar a probar, fui cambiando el valor del rango pero seguía mostrando el mismo error del límite de memoria.

Es verdad lo que respondieron Guillermo y Tordek, el usar el do while no cambia nada, y probé lo sugerido por llarensj y me sirve y mucho,  los txt los uso para ir verificando cada resultado, la verdad me compliqué en generar un array por el hecho que debo seguir procesando cada fila para obtener más datos de la base, pero teniendo el txt puedo ir tomando los datos que necesito para ello.

Sigo trabajando ...

MUCHAS GRACIAS.



--
Gabriel E. Divenuto
Técnico Superior en Sistemas Informáticos
SistemasGD :: Desarrollo de Sistemas Informáticos
Mar del Plata - Argentina
Email: gabriel...@sistemasgd.com.ar
Web:
www.sistemasgd.com

Francisco MC

unread,
Jan 27, 2011, 7:18:33 AM1/27/11
to php...@googlegroups.com
Lo que podes probar para hacer esto es hacer un AJAX y llamar al archivo desde otro.

Donde le pasas como parametros (inicio, fin, destino)

y que te vaya armando el resultado en un txt. cuando termina de dar todos los resultados ahi levantas el txt y lo armas en un PDF o lo mostras.

Saludos.

Francisco Martínez Cevasco

Diseñador Web / Técnico en Artes Multimediales


P: +54 11 6654 0362

E: fmce...@gmail.com

W: www.fmcdesigns.com.ar

My profiles: Facebook LinkedIn Flickr Twitter Blog RSS YouTube


2011/1/27 Gabriel Divenuto <gabriel...@gmail.com>

Guillermo Eduardo Fekete

unread,
Jan 27, 2011, 9:38:27 AM1/27/11
to php...@googlegroups.com
Nunca he tenido que hacerlo pero, si vas a trabajar con un archivo intermedo, creo que será mucho más rapido si lo generas directamente desde el mysql y luego lees el archivo desde php; y no obteniendo los datos en php y generando desde php el archivo para luego leerlo.
(Algo como decirle a mysql que guarde el resultado en un archivo xml y luego leer el archivo desde php. Creo que tanto mysql como php tienen funciones/herramiantes específicas y optiizadas para el trabajo con xml)

saludos a todos

guillermo

Francisco MC

unread,
Jan 27, 2011, 9:56:34 AM1/27/11
to php...@googlegroups.com
Si esa que dice Guillermo es mejor, podes hacerte una función en mysql para esto y evitas trafico y doble manejo de información y optimizas.

Francisco Martínez Cevasco

Diseñador Web / Técnico en Artes Multimediales


P: +54 11 6654 0362

E: fmce...@gmail.com

W: www.fmcdesigns.com.ar

My profiles: Facebook LinkedIn Flickr Twitter Blog RSS YouTube


2011/1/27 Guillermo Eduardo Fekete <guiller...@gmail.com>

Gabriel Divenuto

unread,
Jan 27, 2011, 10:05:53 AM1/27/11
to php...@googlegroups.com
Me dí cuenta que aún teniendo el txt con la información surge el problema del límite de memoria en PHP al intentar leer su contenido, cuando es muy grande.

Voy a hacer lo que me decís Guillermo, gracias.

llarensj

unread,
Jan 27, 2011, 5:23:08 PM1/27/11
to Grupo PHP Argentina
Ah, pero entonces hay una segunda etapa de analisis? Cual deberia ser
el resultado final?

On 27 ene, 12:05, Gabriel Divenuto <gabrieldiven...@gmail.com> wrote:
> Me dí cuenta que aún teniendo el txt con la información surge el problema
> del límite de memoria en PHP al intentar leer su contenido, cuando es muy
> grande.
>
> Voy a hacer lo que me decís Guillermo, gracias.
>
> --
> Gabriel E. Divenuto
> Técnico Superior en Sistemas Informáticos
> SistemasGD :: Desarrollo de Sistemas Informáticos
>  Mar del Plata - Argentina

Tordek

unread,
Jan 27, 2011, 7:54:14 PM1/27/11
to php...@googlegroups.com
2011/1/27 llarensj <llar...@gmail.com>:

> Ah, pero entonces hay una segunda etapa de analisis? Cual deberia ser
> el resultado final?

+1 a esto.

A lo mejor lo podés hacer con un par de queries un poco más complejas,
pero que van a andar mucho más rápido que hacerlo "a mano" via PHP.

Gabriel Divenuto

unread,
Jan 28, 2011, 10:42:33 AM1/28/11
to php...@googlegroups.com
Buen día,
ahora con el resultado de la query armo en una cadena el html para el listado a imprimir, el cual es muy largo.
Creo un archivo en disco y le escribo el contenido de dicha cadena.

Esto para direccionar al html y visualizarlo para la impresión, el problema que tengo es que tarda demasiado para cargarlo en el navegador.

Utilizo la librería html2pdf para generar los listados en PDF, para una impresión más correcta, pero en este caso el listado es muy grande y no me sirve.

Este es un código de prueba para mostrar lo que realizo:
<?php

//SE ABRE LA CONEXION
$conexion = mysql_connect($servidor, $usuario, $password, true, 65536)
or die ("Falló la conexión al Servidor <br>Error: ".mysql_error()."<br>\n");
       
mysql_select_db($base_datos, $conexion) or die("Falló la selección de la Base de Datos <br>Error: ".mysql_error()."<br>\n");

// QUERY DE EJEMPLO, LA REAL DEVUELVE 55,695 FILAS
$sql = "SELECT campo1, campo2, campo3, campo4, campo5, campo6, campo7
    FROM tabla_ejemplo
    WHERE fecha BETWEEN '1983-01-01' AND '2011-01-20'
    ";

// SE EJECUTA LA QUERY
$resultado = mysql_query($sql);

$reporte = "
<html>
  <body>
";
// CONTENIDO
$reporte .= "
<table style=\"border: 2px dotted gray;margin-right:auto;margin-left:auto;\">
      <tr style=\"text-align:center;background-color:#4a6890;color:#fff;padding:3px;\">
    <td>Dato 1</td>
    <td>Dato 2</td>
    <td>Dato 3</td>
    <td>Dato 4</td>
    <td>Dato 5</td>
    <td>Dato 6</td>
    <td>Dato 7</td>
</tr>
";
while ($fila = mysql_fetch_array($resultado, MYSQLI_ASSOC)) {

$reporte .= "  
    <tr>
      <td>".$fila['campo1']."</td>
      <td>".$fila['campo2']."</td>
      <td>".$fila['campo3']."</td>
      <td>".$fila['campo4']."</td>
      <td>".$fila['campo5']."</td>
      <td>".$fila['campo6']."</td>
      <td>".$fila['campo7']."</td>
    </tr>
";
}
$reporte .= "
    </table>
";
$reporte .= "
  </body>
</html>
";

// NOMBRE DEL HTML QUE QUEDA EN DISCO
$nombre_archivo = "reporte.html";
// SE CREA EL ARCHIVO HTML
$archivo = fopen($nombre_archivo, "w");
// SE ESCRIBE EL CONTENIDO ( LISTADO MUY LARGO ) EN EL ARCHIVO
fwrite($archivo,$reporte);
// SE CIERRA EL ARCHIVO
fclose($archivo);

// PARA DESCARGAR EL HTML CREADO
//echo "<a href=\"".$nombre_archivo."\" target=\"_blank\">Descargar</a>";

// Ó PARA DIRECCIONAR A DICHO HTML
//header("Location: ".$nombre_archivo."");

?>

Muchas gracias por la ayuda.




--
Gabriel E. Divenuto
Técnico Superior en Sistemas Informáticos
SistemasGD :: Desarrollo de Sistemas Informáticos
Mar del Plata - Argentina
Email: gabriel...@sistemasgd.com.ar
Web:
www.sistemasgd.com

Gabriel Divenuto

unread,
Jan 28, 2011, 11:30:28 AM1/28/11
to php...@googlegroups.com
Probando con otra librería, DOMPDF:

al final del código anterior, habiendo creado el .html:

ob_start();
include("reporte.html");
$salida_html = ob_get_contents();
ob_end_clean();

require_once("dompdf/dompdf_config.inc.php");
$dompdf = new DOMPDF();
$dompdf->load_html($salida_html);
$dompdf->render();
$dompdf->stream("reporte.pdf");

Devuelve el mismo error de limite de memoria:
   Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 28 bytes) in /var/www/pruebas/pruebas GENERAR REPORTE/dompdf/include/frame_tree.cls.php on line 169

Tordek

unread,
Jan 28, 2011, 1:34:00 PM1/28/11
to php...@googlegroups.com
On 28/01/11 13:30, Gabriel Divenuto wrote:
> Probando con otra librer�a, DOMPDF:
>
> al final del c�digo anterior, habiendo creado el .html:

>
> ob_start();
> include("reporte.html");
> $salida_html = ob_get_contents();
> ob_end_clean();

Ac� quer�s

$salida_html = file_get_contents("reporte.html");

>
> require_once("dompdf/dompdf_config.inc.php");
> $dompdf = new DOMPDF();
> $dompdf->load_html($salida_html);

...o mejor, load_html_file(), que hace lo mismo y te ahorra c�digo.

> $dompdf->render();
> $dompdf->stream("reporte.pdf");
>
> Devuelve el mismo error de limite de memoria:

> *Fatal error*: Allowed memory size of 33554432 bytes exhausted (tried to
> allocate 28 bytes) in */var/www/pruebas/pruebas GENERAR
> REPORTE/dompdf/include/frame_tree.cls.php* on line *169*

Y si eso ya no te funciona (ni expandiendo la memoria disponible
para este script), ya se vuelve m�s f�cil irte a otro lenguaje, como
Python, donde no ten�s el l�mite duro de memoria.

> --
> Gabriel E. Divenuto
> T�cnico Superior en Sistemas Inform�ticos
> SistemasGD :: Desarrollo de Sistemas Inform�ticos


> Mar del Plata - Argentina
> Email: gabriel...@sistemasgd.com.ar

> <http://sistemasgd.com:2084/squirrelmail/src/compose.php?send_to=gabriel...@sistemasgd.com.ar>
> Web: www.sistemasgd.com <http://www.sistemasgd.com/>

--
Guillermo O. �Tordek� Freschi. Programador, Escritor, Genio Maligno.
http://tordek.com.ar :: http://twitter.com/tordek
http://www.arcanopedia.com.ar - Juegos de Rol en Argentina

llarensj

unread,
Jan 28, 2011, 5:30:14 PM1/28/11
to Grupo PHP Argentina
Yo tengo que generar pdf largos tambien, y el dompdf es demasiado
lento para eso. Al final tuve que generarlo directamente con tcpdf
(http://www.tcpdf.org/). Es el mas rapido que probé, al menos hasta
ahora. Con el tema velocidad, tuve que olvidarme de cualquier cosa
intermedia, simplemente a medida que iba obteniendo los registros del
sql iba generando el documento pdf. Lo bueno del tcpdf es que maneja
todo en memoria hasta que le das $objeto->output('file', 'F'). El
segundo parametro es interesante:

I: send the file inline to the browser.
D: send to the browser and force a file download with the name given
by name.
F: save to a local file with the name given by name.
S: return the document as a string. name is ignored.

Adrian Ariza

unread,
Jan 28, 2011, 6:44:39 PM1/28/11
to php...@googlegroups.com
Hola! Si lo que haces es guardar a un arhcivo sin procesar todo el
conjunto me parece que lo que te conviene es algo asi sin usar ningun
array intermedio

0) Abrir el archivo .html para escritura
1) Hacer el query
2) while trayendo las lineas una a una (fetch)
2.1) Ir escribiendo al archivo con los datos de cada linea
3) Cerrar el archivo
4) Free resultado mysql
5) Redirect

No tendrias que tener ningun problema de memoria.
Ahora, si lo que queres es traer todoas los registros, cambiarles el
orden, hacer reportes u otras cosas que requieran tenerlos en memoria,
ahi si seria otra historia.
Suerte!

PD: La verdad que este es el ejemplo tipico que no se como recolver
con MVC ya que generlamente el pasaje es por array... seguramente, no
hay que resolverlo con MVC


2011/1/28 llarensj <llar...@gmail.com>:

Gabriel Divenuto

unread,
Jan 29, 2011, 11:20:51 AM1/29/11
to php...@googlegroups.com
Serializaba el array y lo guardaba en un txt, en el Controlador abría el txt y deserializaba su contenido.

Si no es correcto corríjanme, no quiero confundir a nadie.


Gracias.








--
Gabriel E. Divenuto
Técnico Superior en Sistemas Informáticos
SistemasGD :: Desarrollo de Sistemas Informáticos
Mar del Plata - Argentina
Email: gabriel...@sistemasgd.com.ar
Web:
www.sistemasgd.com

Gabriel Divenuto

unread,
Jan 29, 2011, 11:17:10 AM1/29/11
to php...@googlegroups.com
Voy a probar con tcpdf.

Ahora, si lo que queres es traer todoas los registros, cambiarles el
orden, hacer reportes u otras cosas que requieran tenerlos en memoria,
ahi si seria otra historia.

 Ese es el tema, tengo el resultado, y luego para cada fila debo consultar nuevamente para obtener ciertos datos para dichas filas.
 

PD: La verdad que este es el ejemplo tipico que no se como recolver
con MVC ya que generlamente el pasaje es por array... seguramente, no
hay que resolverlo con MVC

Puedes serializar el array, pasarlo serializado y en el Controlador deserilizarlo para su uso.

Esto lo usaba antes para generar un pdf.

en la Vista:

//SE SERIALIZAN LOS DATOS PARA ENVIARLO AL CONTROLADOR PARA GENERAR EL LISTADO A IMPRIMIR O PROCESAR
    public function array_envia($array, $nombre, $formato) {

    //se serializa el vector de datos recibido
    $tmp = serialize($array);
   
    //Devuelve una cadena en la que todos los caracteres no-alfanumericos excepto -_. han sido
    //reemplazados con un signo de porcentaje (%) seguido por dos digitos hexadecimales y los
    //espacios son codificados como signos de suma (+)   
    $tmp = urlencode($tmp);
   
    $hora_min = explode(':', date("H:i"));
    $hora = $hora_min[0];
    $min = $hora_min[1];
   
    //se compone el nombre del txt a crear
    $archivo_del_documento = $nombre.'_'.$formato.'_'.$_SESSION['usuario'].'_'.$_SESSION['fecha'].'_'.$hora.$min;
    //se crea el .txt y se guarda la serializacion del vector
    fputs(fopen($archivo_del_documento.'.txt','w'),print_r($tmp, true));

    return $archivo_del_documento;
    }

En el Controlador:

 //SE DESERIALIZA UN ARRAY RECIBIDO CON LA INFORMACION (SE LO CONVIERTE A SU VALOR PHP)
    public function array_recibe($url_array) {

    //Devuelve una cadena con las barras invertidas eliminadas (\' se convierte en '),
    //las barras invertidas dobles se convierten en sencillas
    $tmp = stripslashes($url_array);
   
    //Decodifica cualquier cifrado tipo %## en la cadena dada. Se devuelve la cadena decodificada
    $tmp = urldecode($tmp);
   
    //toma una variable sencilla seriada y la convierte de vuelta a su valor PHP
    $tmp = unserialize($tmp);

    // Retorna el array
    return $tmp;
    }

Ahora dejé de usar esto para probar en lo que vienen ayudándome hace rato.




--
Gabriel E. Divenuto
Técnico Superior en Sistemas Informáticos
SistemasGD :: Desarrollo de Sistemas Informáticos
Mar del Plata - Argentina
Email: gabriel...@sistemasgd.com.ar
Web:
www.sistemasgd.com

Adrian Ariza

unread,
Jan 29, 2011, 12:46:49 PM1/29/11
to php...@googlegroups.com
Ok, si necesitas agregar algo a cada linea haciendo otro query yo
haria (y lo hago para cientos de miles de registros)

0) Abrir el archivo .html para escritura

1) Abrir dos conexiones a la base de datos
2) Hacer el query sobre la primer conexion
3) while trayendo las lineas una a una (fetch) del query princiapal
3.1) Query para sacar los datos de cada linea sobre la segunda conexion
3.2) Ir escribiendo al archivo con los datos de cada linea agregando
lo conseguido
4) Cuando termina el ciclo Cerrar el archivo
5) Redirect

Es mas, yo mando la salida linea a linea directamente sin pasar por un
archivo (lo uso mucho para generar CSV dinamicos) y no tengo ningun
problema. Recordar poner los header necesarios

Yo lo uso asi y no tengo problemas de memoria, lo imporante es no
guardar todos los registros a un array.
Espero haber interpretado bien lo que querias hacer.
Suerte!

PD: Lo de serializar puede ser una solucion, pero la verdad es que yo
prefiero analizar porque tengo que hacer tanto trabajo en un pedido
Web, posiblemente ese trabajo lo tenga que hacer un script pero ese es
otro tema. Lo del MVC era solo un comentario, yo si me encuentro que
tengo que pasar tantos datos a la vista, trato de ver si es realmente
necesario.

HQ063

unread,
Jan 29, 2011, 6:43:20 PM1/29/11
to Grupo PHP Argentina
Mira, no leí el 100% de lo que fueron respondiendo, pero si gran
parte.
Por lo que entiendo, te recomiendo probar con complicar la query, ya
que la memoria de mysql no tiene el mismo limite que la de php, hacer
todos los calculos y procesos que necesites en la query, y luego tal
como traes los resultados ir escribiéndolos, sin almacenarlos en
memoria. Si lo que necesitas es agregarle html, podes hacer algo como
esto, que si bien no es "prolijo", en este caso puede servir.
Ademas no entiendo porque necesitas traer mas datos para cada linea,
si eso se puede hacer directamente en la query principal con un join.

SELECT CONCAT('Campo 1: ',campo1,'<br>') as campo1, CONCAT('Campo 2 :
',campo2,'<br>') as campo2, ...
FROM tabla_ejemplo
LEFT JOIN tablas_extra ON ...
WHERE fecha BETWEEN '1983-01-01' AND '2011-01-20'


Disculpen si ya se sugirio algo similar, pero la verdad que estoy de
vacaciones y es bastante freak ya que este leyendolo y respondiendo :P
entre xq me interesaba, pero cuando vi tantas rtas no me tome el
trabajo de leer todo

espero que sirva mi aporte

saludos

On 26 ene, 14:00, Gabriel Divenuto <gabrieldiven...@gmail.com> wrote:
> Email: gabrieldiven...@sistemasgd.com.ar<http://sistemasgd.com:2084/squirrelmail/src/compose.php?send_to=gabrieldiven...@sistemasgd.com.ar>
> Web:www.sistemasgd.com

Francisco MC

unread,
Jan 28, 2011, 11:34:08 AM1/28/11
to php...@googlegroups.com
Probaste lo que te dije del AJAX?, la otra que podes hacer si el .txt te queda muy grandes tambien hacer varios .txt.

Y los van levantando también con otro AJAX al finalizar las consultas.

Saludos
Pancho.

PD: Hola a todos soy nuevo en la lista, espero poder aportar con todo lo que este a mi alcance.

Francisco Martínez Cevasco

Diseñador Web / Técnico en Artes Multimediales


P: +54 11 6654 0362

E: fmce...@gmail.com

W: www.fmcdesigns.com.ar

My profiles: Facebook LinkedIn Flickr Twitter Blog RSS YouTube


2011/1/28 Gabriel Divenuto <gabriel...@gmail.com>

Betos

unread,
Feb 5, 2011, 1:08:16 PM2/5/11
to Grupo PHP Argentina
Hola, he tenido muchas veces que lidiar con los problemas del memory
limit, para solucionarlo cree indices en las tablas que optimizan
bastante el rendimiento al obtener las consultas, aca te dejo un link
para optimizar tu BD,

http://www.programacion.com/articulo/mysql_mas_rapido_187

saludos.

Gabriel Divenuto

unread,
Feb 7, 2011, 7:48:13 AM2/7/11
to php...@googlegroups.com
Buen día, perdón por no contestar antes.

Al ejecutar la query armaba un array para seguir obteniendo datos para cada fila, eso generaba mucho consumo en memoria en el servidor.

Me di cuenta al querer mostrar un listado html con una cantidad grande de datos que el navegador se quedaba cargando demasiado como para generar una versión imprimible.

Por el momento descarté todo esto por el hecho que me confirmaron que tanta cantidad de información se genera muy rara vez, sólo interesa para un rango de años más chico, NO ME CONVENCE NO HABERLO RESUELTO PARA DICHA CANTIDAD, pensé en permitir imprimir por partes, o sea paginando como si de un listado se tratase con la opción de imprimir lo que se muestra y seguir recorriendo para la impresión, muy tedioso pero no me doy cuenta cómo realizarlo de otra manera aún.   

Ahora permito imprimir hasta una cantidad determinada, superando dicha cantidad se le informa al usuario que es muy grande el resultado consultado para impresión.

Ahora sigo con otras cosas pero quiero resolverlo para uso a futuro, me imagino que debe ser una tontería, ya me daré cuenta.

QUIERO AGRADECERLES TODO LO QUE ME AYUDARON Y LO QUE APRENDÍ.

Un saludo.



--
Gabriel E. Divenuto
Técnico Superior en Sistemas Informáticos
SistemasGD :: Desarrollo de Sistemas Informáticos
Mar del Plata - Argentina
Email: gabriel...@sistemasgd.com.ar
Web:
www.sistemasgd.com

Betos

unread,
Feb 8, 2011, 8:27:44 AM2/8/11
to Grupo PHP Argentina
y si probas con usar un sleep(); esto va a retrasar la ejecución
durante el número de segundos y quisas lo podes imprimir de a
fragmentos, seria algo parecido a esto:


<?php

$n = 2; // n segundos
for ($i = 1; $i <= 10; $i++) {
echo $fragmento_.$i;
sleep($n);
}

?>

sebastian larramendy

unread,
May 26, 2015, 2:07:02 PM5/26/15
to php...@googlegroups.com
Hola, buenas! Soy nuevo en el grupo. Buscando una solución a otro problema encontré este tema, el cual yo lo he tenido varias veces.

Probá poniendo ini_set('memory_limit', '-1');
Esa linea debería dejar de limitar el tamaño del array de PHP.

Espero que te sirva, a mi me salvo las papas varias veces.
Abrazo!
--
Gabriel E. Divenuto
Técnico Superior en Sistemas Informáticos
SistemasGD :: Desarrollo de Sistemas Informáticos
Mar del Plata - Argentina

Andrés Morales

unread,
May 26, 2015, 7:54:05 PM5/26/15
to php...@googlegroups.com
Ilimitar el uso de memoria para un script no es una buena práctica para nada. Lo que se puede hacer es optimizar las queries y crear índices en las tablas. Si eso no es suficiente... yo replantearía el código o hasta pensaría en otro motor de DB.

--
Has recibido este mensaje porque estás suscrito al grupo "Grupo PHP Argentina" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a php-arg+u...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a php...@googlegroups.com.
Visita este grupo en http://groups.google.com/group/php-arg.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Guido Robertone

unread,
Jun 2, 2015, 6:25:55 PM6/2/15
to php...@googlegroups.com
Nose si es aplicable los indices ya que obtiene por un rango de fecha. Yo recomendaria que implementes paginacion y devuelvas toda esa busqueda de a porciones...
--
Guido Fernando Robertone
Information Systems Engineer
Team Leader - Sr. Developer
guido.r...@gmail.com
+54-345-154014841
Skype: guido.rob


Reply all
Reply to author
Forward
0 new messages