Me gustaría paginar a través de una lista ordenada aleatoriamente de modelos ActiveRecord (filas de la base de datos MySQL).Clasificación aleatoria estable/repetible (MySQL, Rails)
Sin embargo, esta aleatorización debe continuar por sesión, de modo que otras personas que visiten el sitio web también reciban una lista de registros aleatoria y paginable.
Digamos que hay suficientes entidades (decenas de miles) que el almacenamiento de los valores de ID ordenados aleatoriamente en la sesión o una cookie es demasiado grande, por lo que debo persistir temporalmente de alguna otra manera (MySQL, archivo, etc.)
Inicialmente pensé que podía crear una función basada en la ID de sesión y la ID de página (devolviendo los ID de objeto para esa página), pero dado que los valores ID de objeto en MySQL no son secuenciales (hay espacios), eso parecía desmoronarse mientras lo estaba hurgando. Lo bueno es que requeriría un almacenamiento nulo o mínimo, pero las desventajas son que probablemente sea bastante complejo de implementar y probablemente intensivo en la CPU.
Mi sensación es que debería crear una tabla de intersección, algo así como:
random_sorts(sort_id, created_at, user_id NULL if guest)
random_sort_items(sort_id, item_id, position)
Y luego simplemente almacenar el 'sort_id' en la sesión. Entonces, puedo paginar los random_sorts WHERE sort_id = n ORDER BY position LIMIT ... como de costumbre.
Por supuesto, tendría que poner algún tipo de segador allí para eliminarlos después de un período de inactividad (basado en random_sorts.created_at).
Desafortunadamente, tendría que invalidar la clasificación a medida que se creaban nuevos objetos (y/o se eliminaban los objetos viejos, aunque la eliminación es muy rara). Y, a medida que aumenta la carga, el tamaño/rendimiento de esta tabla (incluso indexado correctamente) disminuye.
Parece que esto debería ser un problema resuelto pero no puedo encontrar ningún complemento de raíles que haga esto ... ¿Alguna idea? ¡¡Gracias!!
Sí, eso funciona siempre que las filas de la tabla nunca cambien (si se agrega una nueva, entiendo que todo el conjunto puede cambiar). Además, ocasiona un escaneo de tabla cada vez, que puede ser un golpe de gran rendimiento ... –
tu comentario parece válido (aunque a veces * quieres * que todo se recurra si la tabla subyacente agrega algo nuevo). Lamentablemente, no puedo pensar en una forma de evitar el escaneo de toda la mesa cada vez, aunque tal vez un 'orden por id límite 10' sea lo suficientemente inteligente como para salir temprano ...). Sin embargo, si no hace una "orden por", agregar una nueva entrada podría aleatorizar su salida, AFAIK, por lo que esta puede ser una pregunta difícil de hacer bien ... – rogerdpack
parece ordenar por rand luego el límite "no "al menos una exploración de tabla completa (en mysql) aunque puede haber trucos que podría usar para evitar acelerar esto en tablas grandes: http://stackoverflow.com/questions/211329/quick-selection-of-a- random-row-from-a-large-table-in-mysql/211388 – rogerdpack