.order('RANDOM()').limit(limit)выглядит аккуратно, но медленно для больших таблиц, потому что он должен извлекать и сортировать все строки, даже если limitравен 1 (внутренне в базе данных, но не в Rails). Я не уверен насчет MySQL, но это происходит в Postgres. Больше объяснений здесь и здесь .
Одним из решений для больших таблиц является то, .from("products TABLESAMPLE SYSTEM(0.5)")где 0.5средства 0.5%. Тем не менее, я считаю, что это решение все еще медленно, если у вас есть WHEREусловия, которые отфильтровывают много строк. Я предполагаю, что это потому, что TABLESAMPLE SYSTEM(0.5)все WHEREусловия выбираются до применения условий.
Другое решение для больших таблиц (но не очень случайное):
products_scope.limit(sample_size).sample(limit)
где sample_sizeможет быть 100(но не слишком большим, иначе он медленный и потребляет много памяти), и limitможет быть 1. Обратите внимание, что, хотя это быстро, но на самом деле не случайно, оно случайно sample_sizeтолько в записях.
PS: результаты тестов в ответах выше не являются надежными (по крайней мере, в Postgres), потому что некоторые запросы к БД, выполняющиеся во 2-й раз, могут быть значительно быстрее, чем в 1-й раз, благодаря кешу БД. И, к сожалению, в Postgres нет простого способа отключить кэш, чтобы сделать эти тесты надежными.