Jadi, saya telah menemukan beberapa contoh untuk menemukan catatan acak di Rails 2 - metode yang disukai tampaknya:
Thing.find :first, :offset => rand(Thing.count)
Menjadi seorang pemula, saya tidak yakin bagaimana ini bisa dibangun menggunakan sintaks find baru di Rails 3.
Jadi, apa "Rails 3 Way" untuk menemukan catatan acak?
Jawaban:
atau
Sebenarnya, dalam Rails 3 semua contoh akan berfungsi. Tetapi menggunakan pesanan
RANDOM
cukup lambat untuk meja besar tetapi lebih gaya sqlUPD. Anda dapat menggunakan trik berikut pada kolom yang diindeks (sintaks PostgreSQL):
sumber
RAND()
atauRANDOM()
. Terima kasihSaya sedang mengerjakan sebuah proyek ( Rails 3.0.15, ruby 1.9.3-p125-perf ) di mana db berada di localhost dan tabel pengguna memiliki catatan lebih dari 100 ribu .
Menggunakan
cukup lambat
menjadi
dan membutuhkan 8 hingga 12 detik untuk merespons !!
Log rel:
dari mysql jelaskan
Anda dapat melihat bahwa tidak ada indeks yang digunakan ( possible_keys = NULL ), sebuah tabel sementara dibuat dan pass tambahan diperlukan untuk mengambil nilai yang diinginkan ( ekstra = Menggunakan sementara; Menggunakan filesort ).
Di sisi lain, dengan memisahkan kueri dalam dua bagian dan menggunakan Ruby, kami memiliki peningkatan yang wajar dalam waktu respons.
(; nihil untuk penggunaan konsol)
Log rel:
dan mysql menjelaskan mengapa:
kita sekarang dapat menggunakan hanya indeks dan kunci utama dan melakukan pekerjaan sekitar 500 kali lebih cepat!
MEMPERBARUI:
seperti yang ditunjukkan oleh icantbecool dalam komentar solusi di atas memiliki kelemahan jika ada catatan yang dihapus dalam tabel.
Solusi yang bisa dilakukan
yang diterjemahkan menjadi dua pertanyaan
dan berjalan sekitar 500ms.
sumber
RAND(id)
akan memberi Anda urutan acak yang berbeda setiap permintaan. Gunakan jika ingin urutan berbeda setiap kueri.RAND()
Jika menggunakan Postgres
Jika menggunakan MySQL
Dalam kedua kasus Anda memilih 5 catatan secara acak dari tabel Pengguna. Berikut adalah query SQL aktual yang ditampilkan di konsol.
sumber
Saya membuat permata 3 rails untuk melakukan ini yang berkinerja lebih baik di meja besar dan memungkinkan Anda untuk menjalin hubungan dan cakupan:
https://github.com/spilliton/randumb
(edit): Perilaku default permata saya pada dasarnya menggunakan pendekatan yang sama seperti di atas sekarang, tetapi Anda memiliki opsi untuk menggunakan cara lama jika mau :)
sumber
Banyak jawaban yang diposting sebenarnya tidak berkinerja baik di tabel yang agak besar (1+ juta baris). Pemesanan acak dengan cepat membutuhkan beberapa detik, dan melakukan penghitungan di atas meja juga memakan waktu yang cukup lama.
Solusi yang berfungsi baik bagi saya dalam situasi ini adalah digunakan
RANDOM()
dengan kondisi di mana:Di atas meja dengan lebih dari satu juta baris, kueri ini biasanya memakan waktu kurang dari 2ms.
sumber
take
fungsi yang memberikanLIMIT(1)
kueri tetapi mengembalikan elemen tunggal, bukan array. Jadi kita tidak perlu memanggilfirst
Kita mulai
cara rel
pemakaian
atau pikiran kedua adalah
pemakaian:
sumber
Couldn't find all Users with 'id': (first, {:offset=>1}) (found 0 results, but was looking for 2)
"RANDOM()"
sebagai gantinya ...Ini sangat berguna bagi saya namun saya membutuhkan sedikit lebih banyak fleksibilitas, jadi inilah yang saya lakukan:
Case1: Menemukan satu sumber rekaman acak : situs trevor turk
Tambahkan ini ke model Thing.rb
maka di controller Anda, Anda dapat memanggil sesuatu seperti ini
Case2: Menemukan beberapa catatan acak (tanpa pengulangan) sumber: tidak dapat mengingat
saya perlu menemukan 10 catatan acak tanpa pengulangan jadi inilah yang saya temukan bekerja
pada controller Anda:
Ini akan menemukan 10 catatan acak, namun perlu disebutkan bahwa jika database sangat besar (jutaan catatan), ini tidak akan ideal, dan kinerja akan terhambat. Apakah akan tampil dengan baik hingga beberapa ribu catatan yang cukup bagi saya.
sumber
Metode Ruby untuk memilih item secara acak dari daftar adalah
sample
. Ingin membuat efisiensample
untuk ActiveRecord, dan berdasarkan jawaban sebelumnya, saya menggunakan:Saya memasukkan ini ke dalam
lib/ext/sample.rb
dan kemudian memuatnya dengan ini diconfig/initializers/monkey_patches.rb
:sumber
#count
akan melakukan panggilan ke DB untuk aCOUNT
. Jika catatan sudah dimuat, ini mungkin ide yang buruk. Sebuah refactor akan digunakan#size
sebagai gantinya karena itu akan memutuskan apakah#count
harus digunakan, atau, jika catatan sudah dimuat, untuk digunakan#length
.count
menjadisize
berdasarkan umpan balik Anda. Info lebih lanjut di: dev.mensfeld.pl/2014/09/...Bekerja di Rails 5 dan DB agnostik:
Ini di controller Anda:
Anda dapat, tentu saja, menaruh kekhawatiran ini seperti yang ditunjukkan di sini .
aplikasi / model / masalah / randomable.rb
kemudian...
app / model / book.rb
Maka Anda dapat menggunakannya hanya dengan melakukan:
atau
sumber
Anda dapat menggunakan sampel () di ActiveRecord
Misalnya
Sumber: http://thinkingeek.com/2011/07/04/easily-select-random-records-rails/
sumber
sample
tidak ada dalam ActiveRecord, sampel ada di Array. api.rubyonrails.org/classes/Array.html#method-i-sampleJika menggunakan Oracle
Keluaran
sumber
Sangat merekomendasikan permata ini untuk catatan acak, yang dirancang khusus untuk tabel dengan banyak baris data:
https://github.com/haopingfan/quick_random_records
Semua jawaban lain berkinerja buruk dengan basis data besar, kecuali permata ini:
4.6ms
total.User.order('RAND()').limit(10)
biaya jawaban yang diterima733.0ms
.offset
pendekatan biaya245.4ms
total.User.all.sample(10)
pendekatan biaya573.4ms
.Catatan: Meja saya hanya memiliki 120.000 pengguna. Semakin banyak catatan yang Anda miliki, semakin besar perbedaan kinerja yang akan terjadi.
MEMPERBARUI:
Tampil di atas meja dengan 550.000 baris
Model.where(id: Model.pluck(:id).sample(10))
biaya1384.0ms
gem: quick_random_records
hanya biaya6.4ms
totalsumber
Cara yang sangat mudah untuk mendapatkan beberapa catatan acak dari tabel. Ini membuat 2 pertanyaan murah.
Model.where(id: Model.pluck(:id).sample(3))
Anda dapat mengubah "3" menjadi jumlah catatan acak yang Anda inginkan.
sumber
Saya baru saja mengalami masalah ini mengembangkan aplikasi kecil di mana saya ingin memilih pertanyaan acak dari DB saya. Saya menggunakan:
Dan itu bekerja dengan baik untuk saya. Saya tidak dapat berbicara tentang bagaimana kinerja untuk DB yang lebih besar karena ini hanya aplikasi kecil.
sumber
shuffle[0]
)