Estoy optimizando muchas consultas existentes en mi proyecto. ¡La solución de Quassnoi me ha ayudado a acelerar mucho las consultas! Sin embargo, encuentro difícil incorporar dicha solución en todas las consultas, especialmente para consultas complicadas que involucran muchas subconsultas en múltiples tablas grandes.
Entonces estoy usando una solución menos optimizada. Fundamentalmente, funciona de la misma manera que la solución de Quassnoi.
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
AND rand() <= $size * $factor / [accomodation_table_row_count]
LIMIT $size
$size * $factor / [accomodation_table_row_count]
calcula la probabilidad de elegir una fila aleatoria. El rand () generará un número aleatorio. La fila se seleccionará si rand () es menor o igual a la probabilidad. Esto efectivamente realiza una selección aleatoria para limitar el tamaño de la mesa. Dado que existe la posibilidad de que devuelva menos que el recuento límite definido, debemos aumentar la probabilidad para asegurarnos de que estamos seleccionando suficientes filas. Por lo tanto, multiplicamos $ size por un $ factor (normalmente establezco $ factor = 2, funciona en la mayoría de los casos). Finalmente hacemos ellimit $size
El problema ahora es resolver el conteo de filas de mesas de alojamiento . Si conocemos el tamaño de la tabla, PODEMOS codificar el tamaño de la tabla. Este sería el más rápido, pero obviamente no es lo ideal. Si está utilizando Myisam, obtener el recuento de tablas es muy eficiente. Como estoy usando innodb, solo estoy haciendo una selección simple de conteo +. En su caso, se vería así:
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
AND rand() <= $size * $factor / (select (SELECT count(*) FROM `accomodation`) * (SELECT count(*) FROM `accomodation_category`))
LIMIT $size
La parte complicada es calcular la probabilidad correcta. Como puede ver, el siguiente código en realidad solo calcula el tamaño aproximado de la tabla de temperatura (de hecho, ¡demasiado aproximado!): (select (SELECT count(*) FROM accomodation) * (SELECT count(*) FROM accomodation_category))
Pero puede refinar esta lógica para dar una aproximación más cercana del tamaño de la tabla. Tenga en cuenta que es mejor SOBRE-seleccionar que sub-seleccionar filas. es decir, si la probabilidad es demasiado baja, corre el riesgo de no seleccionar suficientes filas.
Esta solución funciona más lentamente que la solución de Quassnoi, ya que necesitamos recalcular el tamaño de la tabla. Sin embargo, encuentro esta codificación mucho más manejable. Esta es una compensación entre precisión + rendimiento y complejidad de codificación . Dicho esto, en tablas grandes esto sigue siendo mucho más rápido que Order by Rand ().
Nota: Si la lógica de la consulta lo permite, realice la selección aleatoria lo antes posible antes de cualquier operación de combinación.