Buscador


En todo Internet
En Uterra.Com

Contenidos


Si realizamos una búsqueda en google sobre como realizar una consulta que genere resultados aleatorios, una de las primeras cosas que nos encontramos es que usar en la consulta RAND() o su versión mas eficiente MT_RAND() es poco eficiente y genera un gran consumo de recursos de servidor. Se dice que el uso de MT_RAND() con una consulta LIMIT genera un gran consumo de recursos, pero si lo hacemos con bucles, tal consumo se reduce. Mis comprobaciones más bien han dado un resultado contrario. Además, no encuentro lógica en las afirmaciones en este sentido, sobre todo, por que en ambos métodos es necesario usar MT_RAND(), y en el caso de usar LIMIT, no veo sentido en que el uso de LIMIT, genere tanto consumo de recursos.

Dicho esto, entramos en materia. He desarrollado dos métodos de aleatorización de resultados. El método A usa MT_RAND() y LIMIT, el segundo, método B usa arrays y bucles, donde también es preciso que usemos MT_RAND().

Veamos el método A.

La lógica del método A radica en el uso de LIMIT como forma de determinar desde que resultado mostramos registros, y cuantos registros mostramos. Recordemos la forma de una consulta LIMIT:

LIMIT registro inicial, cuantos registros

Podemos también determinar si lo hacemos en sentido ascendente o descendente mediante ORDER BY campo ASC/DESC. En este sentido, tenemos que tener mucho cuidado con que valor asignamos como inicio del LIMIT. Explico este punto.

Imaginemos que tenemos una tabla con 100 registros, y queremos extraer 10 de manera aleatoria. Cualquiera pensaría en generar un aleatorio entre 1 y 100, pero esto daría menos de 10 registros en algunos casos. Esto ocurriría si el aleatorio fuera 97, por ejemplo, y hemos elegido orden ascendente. En este caso, por encima de 97 solo hay tres registros. Y si el orden es descendente, si el aleatorio fuera 3, por debajo de ese valor, solo tendríamos 2 registros. Por estos motivos, debemos restar del total de registros el número de registros que queremos extraer si nos decantamos por un orden ascendente, o iniciar el LIMIT en el número de registros que queremos extraer si usamos el orden descendente.

Este método de aleatorización tiene un problema, y es que como solo se determina de manera aleatoria el comienzo del LIMIT, los demás registros siempre serán los adyacentes a este, por encima o por debajo según el orden que asignemos.

Dicho esto, el resto del código no tiene ninguna novedad respecto a una lectura de tabla ordinaria. Presentamos este código como “Método A”.

Veamos ahora el método B.

Este metido sigue una lógica diferente y no radica en el tipo de consulta SQL como en el caso anterior. Ahora lo que hacemos es generar un array con los registros de la tabla. Generamos mediante un buble un grupo de valores aleatorios, tantos como resultados queremos obtener, y se corresponden con el rango de valores de las claves del array. Con esto, teniendo las claves, ya podemos obtener los valores del array, y estos son nuestros resultados aleatorios.

Este método tiene una ventaja sobre el anterior, y es que los resultados son realmente aleatorios (mas bien seudoaleatorios, ya que MT_RAND() genera valores seudoaleatorios).

Este método, si bien tiene este ultima ventaja, consume mas recursos de servidor que el metido A, considerado el “peor” en la mayoría de los sitios Web consultados. Y consume mas recursos que el anterior, por que si bien en el método A solo hay un solo bucle while, en el método B hay tres bucles, uno while, uno for y otro foreach. Presentamos este código como “Método B”.

Para comprobar esto, he agregado una medición de recursos de memoria consumida al inicio y al final de cada código. Que cada cual saque sus conclusiones y elija la opción que mas convenga a sus necesidades. 

============= METODO A: Registros aleatorios con LIMIT.
<!DOCTYPE html> 
<html lang="es"> 
<head>
    <meta charset="iso-8859-1" />
    <title>Registros aleatorios de una consulta MySQL usando RAND y LIMIT.</title>
    <meta name="robots" content="noindex, nofollow" />

</head>

<body>

<H3 align="center">METODO A: Registros aleatorios con LIMIT.</H3>

<div align="center">
    <table border="1" width="700" id="table1">
<?php 

    error_reporting
(-1);
    
ini_set("display_errors"1);

// MEDIMOS LA MEMORIA CONSUMIDA EN LA EJECUCION DEL CODIGO ANTES 
// DE INICIAR LA CONEXION A LA BASE DE DATOS

// Muestra la memoria usada antes de ejecutar el codigo 

    
$memoria_antes memory_get_usage(); 

    
$memoria_antes_kb round($memoria_antes 10242); 

    
// echo "$memoria_antes_kb Kb <br />"; 
    
// FIN DE LA MEDICION DE MEMORIA CONSUMIDA ANTES DE EJECUTAR EL CODIGO
    
include("../abre_conexion.php"); 

// Generamos una consulta que muestra resultados aleatorios

// ------ Contamos numero de registros 
        
$_Cuen_1 " SELECT * FROM $tabla_db1 ";   
        
$_Cuenta_1 mysql_query($_Cuen_1);   
        
$_Total_1 mysql_num_rows($_Cuenta_1); 

    
$total_resgistros $_Total_1;    // Total registros en la tabla
    
$n_registros 10;            // <<<<<<<<< Numero de registros a generar MODIFICAR
    
$aleatorio mt_rand(1$total_resgistros $n_registros);

    
$_pagi_sql " SELECT id, nombre, email, fecha, hora FROM $tabla_db1 ORDER BY id ASC LIMIT $aleatorio$n_registros ";  
    
$_pagi_result mysql_query($_pagi_sql);  

while (
$registro mysql_fetch_array($_pagi_result)){  
                
                echo 

                    <tr> 
                            <td class=\"celda1\">"
.$registro['id']."</td> 
                            <td class=\"celda1\">"
.$registro['nombre']."</td> 
                            <td class=\"celda1\">"
.$registro['email']."</td> 
                            <td class=\"celda1\">"
.$registro['fecha']."</td>
                            <td class=\"celda1\">"
.$registro['hora']."</td>
                    </tr> 
                "

}
include(
"../cierra_conexion.php"); 

// MEDIMOS LA MEMORIA CONSUMIDA EN LA EJECUCION DEL CODIGO DESPUES 
// DE INICIAR LA CONEXION A LA BASE DE DATOS
// Muestra la memoria usada despues de ejecutar el codigo 

    
$memoria_despues memory_get_usage(); 

    
$memoria_despues_kb round($memoria_despues 10242); 
    
    
// echo "$memoria_despues_kb Kb <br />"; 

    
$memoria_usada $memoria_despues $memoria_antes

    
$_memoria_antes round($memoria_antes 10242);
    
$_memoria_despues round($memoria_despues 10242);
    
$_memoria_usada round($memoria_usada 10242);
    
    
$porcentaje round(($memoria_usada 100) / $memoria_antes2);

// FIN DE LA MEDICION DE MEMORIA CONSUMIDA DESPUES DE EJECUTAR EL CODIGO
    
echo "
    </table>
</div>
    <p>
        Memoria consumida antes de la ejecucion de la consulta: 
$_memoria_antes Kb <br />
        Memoria consumida despues de la ejecucion de la consulta: 
$_memoria_despues Kb <br />
        Memoria consumida por la ejecucion de la consulta: 
$_memoria_usada Kb <br />
        Incremento de memoria consumida: 
$porcentaje%
    </p>"

?>
<p align="center"><a target="_blank" href="../id103/lista2.php">Tabla de donde extraemos los resgistros aleatorios</a></p>
<p align="center"><a href="reg_aleatorios.php">Generador de aleatorios con bucles en MySQL</a></p>
</body>

</html>
================================================================================
============= METODO B: Registros aleatorios con BUCLES.
<!DOCTYPE html> 
<html lang="es"> 
<head>
    <meta charset="iso-8859-1" />
    <title>Registros aleatorios de una consulta MySQL usando bucles.</title>
    <meta name="robots" content="noindex, nofollow" />

</head>

<body>

<H3 align="center">METODO B: Registros aleatorios con BUCLES.</H3>

<div align="center">
    <table border="1" width="700" id="table1">
<?php 

    error_reporting
(-1);
    
ini_set("display_errors"1);
    
// MEDIMOS LA MEMORIA CONSUMIDA EN LA EJECUCION DEL CODIGO ANTES 
// DE INICIAR LA CONEXION A LA BASE DE DATOS

// Muestra la memoria usada antes de ejecutar el codigo 

    
$memoria_antes memory_get_usage(); 

    
$memoria_antes_kb round($memoria_antes 10242); 

    
// echo "$memoria_antes_kb Kb <br />"; 
    
// FIN DE LA MEDICION DE MEMORIA CONSUMIDA ANTES DE EJECUTAR EL CODIGO

include("../abre_conexion.php"); 

// Generamos una consulta que muestra resultados aleatorios

    
$_pagi_sql " SELECT id, nombre, email, fecha, hora FROM $tabla_db1 ";  
    
$_pagi_result mysql_query($_pagi_sql);   
    
$_total_registros mysql_num_rows($_pagi_result);   

    
$array_multi_registro = array();     // Creamos array 
    
$i 0
     
    while(
$registro mysql_fetch_array($_pagi_result)) { 

        
$array_multi_registro[$i] = $registro
        
$i++; 
        
        
$n_elemen_array count($array_multi_registro); 
    }
    
        
$Num_Regis 10;    // <<<<<<<<< Numero de registros a generar MODIFICAR
    
            
$_Val_min 0;    // Valor minimo 
            
$_Val_max $n_elemen_array 1;    // Valor maximo 
        
        
if($Num_Regis $_Val_max) {
            
            echo 
"<p>No es posible generar $Num_Regis registros aleatorios por la que tabla contine $_Val_max registros.</p>"
            
        } else {
                
$_nuM = Array(); 
                
reset($_nuM); 
                    for(
$i=1$i<=$Num_Regis$i++) { 
                    
$_nuM[$i]=MT_RAND($_Val_min$_Val_max); if($i>1) { 
                            for(
$x=1$x<$i$x++) { if($_nuM[$i]==$_nuM[$x]) { $i--;  
                                    break; } } } } 

            foreach(
$_nuM as $array_reg) { 

                @
$reg_id $array_multi_registro[$array_reg][id];
                @
$reg_nombre $array_multi_registro[$array_reg][nombre]; 
                @
$reg_email $array_multi_registro[$array_reg][email]; 
                @
$reg_fecha $array_multi_registro[$array_reg][fecha];
                @
$reg_hora $array_multi_registro[$array_reg][hora];
                
                echo 

                    <tr> 
                            <td class=\"celda1\">
$reg_id</td> 
                            <td class=\"celda1\">
$reg_nombre</td> 
                            <td class=\"celda1\">
$reg_email</td> 
                            <td class=\"celda1\">
$reg_fecha</td> 
                            <td class=\"celda1\">
$reg_hora</td>
                    </tr> 
                "

            } 
        }
include(
"../cierra_conexion.php"); 

// MEDIMOS LA MEMORIA CONSUMIDA EN LA EJECUCION DEL CODIGO DESPUES 
// DE INICIAR LA CONEXION A LA BASE DE DATOS
// Muestra la memoria usada despues de ejecutar el codigo 

    
$memoria_despues memory_get_usage(); 

    
$memoria_despues_kb round($memoria_despues 10242); 
    
    
// echo "$memoria_despues_kb Kb <br />"; 

    
$memoria_usada $memoria_despues $memoria_antes

    
$_memoria_antes round($memoria_antes 10242);
    
$_memoria_despues round($memoria_despues 10242);
    
$_memoria_usada round($memoria_usada 10242);
    
    
$porcentaje round(($memoria_usada 100) / $memoria_antes2);

// FIN DE LA MEDICION DE MEMORIA CONSUMIDA DESPUES DE EJECUTAR EL CODIGO

echo "
    </table>
</div>
    <p>
        Memoria consumida antes de la ejecucion de la consulta: 
$_memoria_antes Kb <br />
        Memoria consumida despues de la ejecucion de la consulta: 
$_memoria_despues Kb <br />
        Memoria consumida por la ejecucion de la consulta: 
$_memoria_usada Kb <br />
        Incremento de memoria consumida: 
$porcentaje%
    </p>"

?>
<p align="center"><a target="_blank" href="../id103/lista2.php">Tabla de donde extraemos los resgistros aleatorios</a></p>
<p align="center"><a href="reg_aleatorios_limit.php">Generador de aleatorios con LIMIT en MySQL</a></p>
</body>

</html>