J'ai donc trouvé plusieurs exemples pour trouver un enregistrement aléatoire dans Rails 2 - la méthode préférée semble être:
Thing.find :first, :offset => rand(Thing.count)
Étant un débutant, je ne sais pas comment cela pourrait être construit en utilisant la nouvelle syntaxe de recherche dans Rails 3.
Alors, quel est le "Rails 3 Way" pour trouver un enregistrement aléatoire?
Réponses:
ou
En fait, dans Rails 3, tous les exemples fonctionneront. Mais l'utilisation de l'ordre
RANDOM
est assez lente pour les grandes tables mais plus de style SQLUPD. Vous pouvez utiliser l'astuce suivante sur une colonne indexée (syntaxe PostgreSQL):
la source
RAND()
ouRANDOM()
. MerciJe travaille sur un projet ( Rails 3.0.15, ruby 1.9.3-p125-perf ) où se trouve la base de données localhost et la table des utilisateurs a un peu plus de 100K enregistrements .
En utilisant
est assez lent
devient
et prend de 8 à 12 secondes pour répondre !!
Journal des rails:
de mysql's expliquer
Vous pouvez voir qu'aucun index n'est utilisé ( possible_keys = NULL ), une table temporaire est créée et une passe supplémentaire est requise pour récupérer la valeur souhaitée ( extra = Utilisation temporaire; Utilisation de filesort ).
D'autre part, en divisant la requête en deux parties et en utilisant Ruby, nous avons une amélioration raisonnable du temps de réponse.
(; nul pour l'utilisation de la console)
Journal des rails:
et mysql's expliquent pourquoi:
nous pouvons maintenant utiliser uniquement les index et la clé primaire et faire le travail environ 500 fois plus vite!
METTRE À JOUR:
comme indiqué par icantbecool dans les commentaires, la solution ci-dessus présente un défaut s'il y a des enregistrements supprimés dans le tableau.
Une solution de contournement qui peut être
ce qui se traduit par deux requêtes
et fonctionne en environ 500 ms.
la source
RAND(id)
ne vous donnera PAS un ordre aléatoire différent à chaque requête. UtilisezRAND()
si vous voulez un ordre différent à chaque requête.Si vous utilisez Postgres
Si vous utilisez MySQL
Dans les deux cas, vous sélectionnez 5 enregistrements au hasard dans la table Users. Voici la requête SQL réelle affichée dans la console.
la source
J'ai fait une gemme de rails 3 pour faire cela qui fonctionne mieux sur les grandes tables et vous permet d'enchaîner les relations et les portées:
https://github.com/spilliton/randumb
(modifier): Le comportement par défaut de ma gemme utilise essentiellement la même approche que ci-dessus maintenant, mais vous avez la possibilité d'utiliser l'ancienne méthode si vous le souhaitez :)
la source
La plupart des réponses publiées ne fonctionnent pas bien sur des tableaux assez volumineux (1 + million de lignes). La commande aléatoire prend rapidement quelques secondes, et faire un compte sur la table prend également assez de temps.
Une solution qui fonctionne bien pour moi dans cette situation est d'utiliser
RANDOM()
avec une condition where:Sur une table de plus d'un million de lignes, cette requête prend généralement moins de 2 ms.
la source
take
fonction qui donne uneLIMIT(1)
requête mais renvoie un élément unique au lieu d'un tableau. Nous n'avons donc pas besoin d'invoquerfirst
Et c'est parti
voie de rails
usage
ou la seconde pensée est
usage:
la source
Couldn't find all Users with 'id': (first, {:offset=>1}) (found 0 results, but was looking for 2)
"RANDOM()"
place ...Cela m'a été très utile mais j'avais besoin d'un peu plus de flexibilité, c'est donc ce que j'ai fait:
Cas 1: Recherche d'une source d' enregistrement aléatoire : site
de trevor turk Ajoutez ceci au modèle Thing.rb
alors dans votre contrôleur, vous pouvez appeler quelque chose comme ça
Cas 2: Recherche de plusieurs enregistrements aléatoires (sans répétition) source:
je ne me souviens pas que j'avais besoin de trouver 10 enregistrements aléatoires sans répétition, voici donc ce que j'ai trouvé fonctionné
dans votre contrôleur:
Cela permettra de trouver 10 enregistrements aléatoires, mais il convient de mentionner que si la base de données est particulièrement volumineuse (des millions d'enregistrements), ce ne serait pas idéal et les performances en seraient affectées. Il fonctionnera bien jusqu'à quelques milliers de disques, ce qui me suffisait.
la source
La méthode Ruby pour choisir au hasard un élément dans une liste est
sample
. Voulant créer un efficacesample
pour ActiveRecord, et sur la base des réponses précédentes, j'ai utilisé:Je mets ceci
lib/ext/sample.rb
et puis le charge avec ceci dansconfig/initializers/monkey_patches.rb
:la source
#count
fera un appel à la base de données pour un fichierCOUNT
. Si l'enregistrement est déjà chargé, cela peut être une mauvaise idée. Un refactor serait à utiliser à la#size
place car il décidera s'il#count
doit être utilisé, ou, si l'enregistrement est déjà chargé, à utiliser#length
.count
à ensize
fonction de vos commentaires. Plus d'infos sur: dev.mensfeld.pl/2014/09/…Fonctionne dans Rails 5 et est indépendant de DB:
Ceci dans votre contrôleur:
Vous pouvez, bien sûr, mettre cela dans un souci comme indiqué ici .
app / modèles / préoccupations / randomable.rb
puis...
app / models / book.rb
Ensuite, vous pouvez utiliser simplement en faisant:
ou
la source
Vous pouvez utiliser sample () dans ActiveRecord
Par exemple
Source: http://thinkingeek.com/2011/07/04/easily-select-random-records-rails/
la source
sample
n'est pas dans ActiveRecord, l'échantillon est dans Array. api.rubyonrails.org/classes/Array.html#method-i-sampleSi vous utilisez Oracle
Production
la source
Je recommande vivement ce joyau pour les enregistrements aléatoires, spécialement conçu pour les tables avec beaucoup de lignes de données:
https://github.com/haopingfan/quick_random_records
Toutes les autres réponses fonctionnent mal avec une grande base de données, à l'exception de ce joyau:
4.6ms
totalement.User.order('RAND()').limit(10)
coût de la réponse acceptée733.0ms
.offset
approche a coûté245.4ms
totalement.User.all.sample(10)
coût d'approche573.4ms
.Remarque: ma table ne compte que 120 000 utilisateurs. Plus vous avez d'enregistrements, plus la différence de performances sera énorme.
METTRE À JOUR:
Performer sur une table de 550000 lignes
Model.where(id: Model.pluck(:id).sample(10))
Coût1384.0ms
gem: quick_random_records
ne coûte que6.4ms
totalementla source
Un moyen très simple d'obtenir plusieurs enregistrements aléatoires de la table. Cela fait 2 requêtes bon marché.
Model.where(id: Model.pluck(:id).sample(3))
Vous pouvez changer le "3" pour le nombre d'enregistrements aléatoires que vous voulez.
la source
Je viens de rencontrer ce problème en développant une petite application dans laquelle je voulais sélectionner une question aléatoire dans ma base de données. J'ai utilisé:
Et ça marche bien pour moi. Je ne peux pas parler des performances des bases de données plus importantes, car il ne s'agit que d'une petite application.
la source
shuffle[0]
)