.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: Результати Benchmark у відповідях вище не є надійними (принаймні, у Postgres), тому що деякі запити БД, які виконуються у 2-й час, можуть бути значно швидшими, ніж виконання у 1-й раз, завдяки кешу DB. І, на жаль, не існує простого способу відключити кеш в Postgres, щоб зробити ці орієнтири надійними.