.order('RANDOM()').limit(limit)wygląda schludnie, ale działa wolno w przypadku dużych tabel, ponieważ musi pobrać i posortować wszystkie wiersze, nawet jeśli limitma wartość 1 (wewnętrznie w bazie danych, ale nie w Railsach). Nie jestem pewien co do MySQL, ale dzieje się tak w Postgres. Więcej wyjaśnień tutaj i tutaj .
Jednym z rozwiązań dla dużych stołów jest .from("products TABLESAMPLE SYSTEM(0.5)")to, co 0.5oznacza 0.5%. Jednak uważam, że to rozwiązanie jest nadal powolne, jeśli masz WHEREwarunki, które odfiltrowują wiele wierszy. Wydaje mi się, że to dlatego, że wcześniej TABLESAMPLE SYSTEM(0.5)pobierz wszystkie wierszeWHERE zastosowaniem warunków.
Innym rozwiązaniem dla dużych tabel (ale niezbyt losowych) jest:
products_scope.limit(sample_size).sample(limit)
gdzie sample_sizemoże być 100(ale nie za duży, w przeciwnym razie jest powolny i zużywa dużo pamięci) i limitmoże być 1. Zauważ, że chociaż jest to szybkie, ale nie jest to przypadkowe, jest losowe sample_sizetylko w rekordach.
PS: Wyniki testów porównawczych w powyższych odpowiedziach nie są wiarygodne (przynajmniej w Postgres), ponieważ niektóre zapytania DB uruchomione po raz drugi mogą być znacznie szybsze niż uruchomione za pierwszym razem, dzięki pamięci podręcznej DB. I niestety nie ma łatwego sposobu na wyłączenie pamięci podręcznej w Postgres, aby te testy były wiarygodne.