Daher habe ich in Rails 2 mehrere Beispiele für das Auffinden eines zufälligen Datensatzes gefunden - die bevorzugte Methode scheint zu sein:
Thing.find :first, :offset => rand(Thing.count)
Als Neuling bin ich mir nicht sicher, wie dies mit der neuen Find-Syntax in Rails 3 konstruiert werden kann.
Also, was ist der "Rails 3 Way", um einen zufälligen Datensatz zu finden?
Antworten:
oder
Tatsächlich funktionieren in Rails 3 alle Beispiele. Die Verwendung von Order
RANDOM
ist für große Tische jedoch recht langsam, jedoch eher im SQL-StilUPD. Sie können den folgenden Trick für eine indizierte Spalte verwenden (PostgreSQL-Syntax):
quelle
RAND()
oderRANDOM()
. DankeIch arbeite an einem Projekt ( Rails 3.0.15, Ruby 1.9.3-p125-perf ), bei dem sich die Datenbank in localhost befindet und die Benutzertabelle etwas mehr als 100.000 Datensätze enthält .
Verwenden von
ist ziemlich langsam
wird
und dauert 8 bis 12 Sekunden zu antworten !!
Schienenprotokoll:
von mysql erklären
Sie können sehen, dass kein Index verwendet wird ( simply_keys = NULL ), eine temporäre Tabelle erstellt wird und ein zusätzlicher Durchgang erforderlich ist, um den gewünschten Wert abzurufen ( extra = Temporär verwenden; Dateisortierung verwenden ).
Auf der anderen Seite haben wir durch die Aufteilung der Abfrage in zwei Teile und die Verwendung von Ruby eine angemessene Verbesserung der Antwortzeit.
(; Null für Konsolengebrauch)
Schienenprotokoll:
und mysqls erklären beweist warum:
Wir können jetzt nur noch Indizes und den Primärschlüssel verwenden und die Arbeit ungefähr 500 Mal schneller erledigen!
AKTUALISIEREN:
Wie von icantbecool in den Kommentaren hervorgehoben, weist die obige Lösung einen Fehler auf, wenn gelöschte Datensätze in der Tabelle enthalten sind.
Eine Problemumgehung kann sein
was zu zwei Abfragen übersetzt
und läuft in ca. 500ms.
quelle
RAND(id)
wird nicht Ihnen eine andere zufällige Reihenfolge jede Abfrage geben. Verwenden Sie,RAND()
wenn Sie eine andere Reihenfolge für jede Abfrage wünschen.Bei Verwendung von Postgres
Bei Verwendung von MySQL
In beiden Fällen wählen Sie 5 Datensätze zufällig aus der Benutzertabelle aus. Hier wird die aktuelle SQL-Abfrage in der Konsole angezeigt.
quelle
Ich habe dafür ein Rails 3-Juwel erstellt, das auf großen Tischen eine bessere Leistung erbringt und es Ihnen ermöglicht, Beziehungen und Bereiche zu verketten:
https://github.com/spilliton/randumb
(Bearbeiten): Das Standardverhalten meines Edelsteins verwendet im Grunde den gleichen Ansatz wie oben, aber Sie haben die Möglichkeit, den alten Weg zu verwenden, wenn Sie möchten :)
quelle
Viele der veröffentlichten Antworten funktionieren in ziemlich großen Tabellen (über 1 Million Zeilen) nicht gut. Die zufällige Bestellung dauert schnell einige Sekunden, und das Zählen auf dem Tisch dauert ebenfalls ziemlich lange.
Eine Lösung, die in dieser Situation für mich gut funktioniert, ist die Verwendung
RANDOM()
mit einer where-Bedingung:In einer Tabelle mit über einer Million Zeilen dauert diese Abfrage im Allgemeinen weniger als 2 ms.
quelle
take
Funktion, die eineLIMIT(1)
Abfrage ausgibt, jedoch ein einzelnes Element anstelle eines Arrays zurückgibt. So dass wir nicht aufrufen müssenfirst
Auf geht's
Schienen Weg
Verwendung
oder der zweite Gedanke ist
Verwendung:
quelle
Couldn't find all Users with 'id': (first, {:offset=>1}) (found 0 results, but was looking for 2)
"RANDOM()"
stattdessen verwenden ...Das war sehr nützlich für mich, aber ich brauchte etwas mehr Flexibilität, also habe ich Folgendes getan:
Fall 1: Finden einer zufälligen Datensatzquelle : Trevor Turk Site
Fügen Sie diese zum Thing.rb-Modell hinzu
dann können Sie in Ihrem Controller so etwas aufrufen
Fall 2: Finden mehrerer zufälliger Datensätze (keine Wiederholungen) Quelle:
Ich kann mich nicht erinnern, dass ich 10 zufällige Datensätze ohne Wiederholungen suchen musste. Ich fand, dass dies
in Ihrem Controller funktioniert hat :
Dabei werden 10 zufällige Datensätze gefunden. Es ist jedoch erwähnenswert, dass eine besonders große Datenbank (Millionen von Datensätzen) nicht ideal ist und die Leistung beeinträchtigt wird. Es wird bis zu ein paar tausend Platten gut abschneiden, was für mich ausreichend war.
quelle
Die Ruby-Methode zum zufälligen Auswählen eines Elements aus einer Liste lautet
sample
. Um ein effizientessample
für ActiveRecord zu erstellen und basierend auf den vorherigen Antworten, habe ich verwendet:Ich lege dies ein
lib/ext/sample.rb
und lade es dann mitconfig/initializers/monkey_patches.rb
:quelle
#count
wird ein Aufruf an die DB für aCOUNT
. Wenn der Datensatz bereits geladen ist, ist dies möglicherweise eine schlechte Idee.#size
Stattdessen#count
sollte ein Refactor verwendet werden, da er entscheidet, ob er verwendet werden soll oder, falls der Datensatz bereits geladen ist, verwendet werden soll#length
.count
zusize
basierend auf Ihrem Feedback. Weitere Infos unter: dev.mensfeld.pl/2014/09/…Funktioniert in Rails 5 und ist DB-unabhängig:
Dies in Ihrem Controller:
Sie können dies natürlich in ein Problem bringen, wie hier gezeigt .
App / Modelle / Anliegen / randomable.rb
dann...
app / models / book.rb.
Dann können Sie einfach verwenden, indem Sie:
oder
quelle
Sie können sample () in ActiveRecord verwenden
Z.B
Quelle: http://thinkingeek.com/2011/07/04/easily-select-random-records-rails/
quelle
sample
ist nicht in ActiveRecord, Beispiel ist in Array. api.rubyonrails.org/classes/Array.html#method-i-sampleBei Verwendung von Oracle
Ausgabe
quelle
Empfehlen Sie dieses Juwel dringend für zufällige Datensätze, das speziell für Tabellen mit vielen Datenzeilen entwickelt wurde:
https://github.com/haopingfan/quick_random_records
Alle anderen Antworten funktionieren mit einer großen Datenbank schlecht, mit Ausnahme dieses Edelsteins:
4.6ms
total.User.order('RAND()').limit(10)
Kosten733.0ms
.offset
Ansatz kostete245.4ms
total.User.all.sample(10)
Anflugkosten573.4ms
.Hinweis: Meine Tabelle hat nur 120.000 Benutzer. Je mehr Datensätze Sie haben, desto größer wird der Leistungsunterschied sein.
AKTUALISIEREN:
Führen Sie eine Tabelle mit 550.000 Zeilen durch
Model.where(id: Model.pluck(:id).sample(10))
kosten1384.0ms
gem: quick_random_records
kostet nur6.4ms
totalquelle
Eine sehr einfache Möglichkeit, mehrere zufällige Datensätze aus der Tabelle abzurufen. Dies macht 2 billige Anfragen.
Model.where(id: Model.pluck(:id).sample(3))
Sie können die "3" in die Anzahl der gewünschten zufälligen Datensätze ändern.
quelle
Ich bin gerade auf dieses Problem gestoßen, als ich eine kleine Anwendung entwickelt habe, in der ich eine zufällige Frage aus meiner Datenbank auswählen wollte. Ich benutzte:
Und es funktioniert gut für mich. Ich kann nicht darüber sprechen, wie die Leistung für größere DBs ist, da dies nur eine kleine Anwendung ist.
quelle
shuffle[0]
)