.order('RANDOM()').limit(limit)
sieht ordentlich aus, ist aber für große Tabellen langsam, da alle Zeilen abgerufen und sortiert werden müssen, auch wenn sie limit
1 sind (intern in der Datenbank, aber nicht in Rails). Ich bin mir bei MySQL nicht sicher, aber das passiert in Postgres. Weitere Erklärungen hier und hier .
Eine Lösung für große Tische ist .from("products TABLESAMPLE SYSTEM(0.5)")
wo 0.5
Mittel 0.5%
. Ich finde jedoch, dass diese Lösung immer noch langsam ist, wenn Sie WHERE
Bedingungen haben, die viele Zeilen herausfiltern. Ich denke, das liegt daran, dass TABLESAMPLE SYSTEM(0.5)
alle Zeilen zuvor abgerufen wurdenWHERE
Bedingungen zutreffen.
Eine andere Lösung für große Tabellen (aber nicht sehr zufällig) ist:
products_scope.limit(sample_size).sample(limit)
wo sample_size
kann sein 100
(aber nicht zu groß, sonst ist es langsam und verbraucht viel Speicher) und limit
kann sein 1
. Beachten Sie, dass dies zwar schnell ist, aber nicht wirklich zufällig, sondern sample_size
nur innerhalb von Datensätzen zufällig .
PS: Benchmark-Ergebnisse in den obigen Antworten sind nicht zuverlässig (zumindest in Postgres), da einige DB-Abfragen, die zum zweiten Mal ausgeführt werden, dank des DB-Caches erheblich schneller sein können als zum ersten Mal. Und leider gibt es keine einfache Möglichkeit, den Cache in Postgres zu deaktivieren, um diese Benchmarks zuverlässig zu machen.