[RUBY-ON-RAILS] 3 레일 : 임의의 레코드를 가져
RUBY-ON-RAILS3 레일 : 임의의 레코드를 가져
그래서, 레일 2 임의의 기록을 찾기 위해 몇 가지 예를 발견했습니다 - 선호되는 방법은 것 같다 :
Thing.find :first, :offset => rand(Thing.count)
초보자의 일이기 때문에 나는이 레일 3의 새 발견 구문을 사용하여 구성 할 수있는 방법을 모르겠어요.
따라서, 임의의 기록을 찾을 수있는 "레일 3 자"는 무엇인가요?
해결법
-
==============================
1.
Thing.first(:order => "RANDOM()") # For MySQL :order => "RAND()", - thanx, @DanSingerman # Rails 3 Thing.order("RANDOM()").first
또는
Thing.first(:offset => rand(Thing.count)) # Rails 3 Thing.offset(rand(Thing.count)).first
사실, 레일 3의 모든 예제는 작동합니다. 그러나 사용 순서 RANDOM 큰 테이블 만 이상의 SQL 스타일에 대한 매우 느린
UPD. 당신은 인덱스 컬럼 (PostgreSQL의 구문)에 다음과 같은 트릭을 사용할 수 있습니다 :
select * from my_table where id >= trunc( random() * (select max(id) from my_table) + 1 ) order by id limit 1;
-
==============================
2.DB를 로컬 호스트에있는 사용자 테이블이 조금 이상 100K 레코드가 어디 프로젝트를 진행하고있다 (1.9.3-P125-반환 한 루비, 3.0.15 레일).
DB를 로컬 호스트에있는 사용자 테이블이 조금 이상 100K 레코드가 어디 프로젝트를 진행하고있다 (1.9.3-P125-반환 한 루비, 3.0.15 레일).
사용
아주 느린
가된다
및 응답에 8 ~ 12 초 정도 소요!
레일 로그 :
MySQL의의 설명에서
+----+-------------+-------+------+---------------+------+---------+------+--------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+--------+---------------------------------+ | 1 | SIMPLE | users | ALL | NULL | NULL | NULL | NULL | 110165 | Using temporary; Using filesort | +----+-------------+-------+------+---------------+------+---------+------+--------+---------------------------------+
당신은 인덱스를 사용하지 않는 것을 볼 수 있습니다 (이 possible_keys = NULL), 임시 테이블이 생성되고 추가 패스가 원하는 값 가져 오기 위해 필요하다 (임시 사용하여 추가 =을, filesort를 사용).
반면에, 분할에 의해 두 부분으로 루비를 사용에서 쿼리, 우리는 응답 시간의 합리적인 개선이있다.
users = User.scoped.select(:id);nil User.find( users.first( Random.rand( users.length )).last )
(; 콘솔 사용하기위한 무기 호)
레일 로그 :
과의 설명 MySQL의 이유를 증명한다 :
+----+-------------+-------+-------+---------------+--------------------------+---------+------+--------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+--------------------------+---------+------+--------+-------------+ | 1 | SIMPLE | users | index | NULL | index_users_on_user_type | 2 | NULL | 110165 | Using index | +----+-------------+-------+-------+---------------+--------------------------+---------+------+--------+-------------+ +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
우리는 이제 인덱스와 기본 키를 사용하여 약 500 배 빠른 작업을 할 수있다!
최신 정보:
표에 기록이 삭제 된 경우 주석 icantbecool가 가리키는 아웃으로 위의 솔루션은 결함이있다.
그의 해결 방법이 될 수 있습니다
users_count = User.count User.scoped.limit(1).offset(rand(users_count)).first
두 쿼리에있는 변환
SELECT COUNT(*) FROM `users` SELECT `users`.* FROM `users` LIMIT 1 OFFSET 148794
및은 500ms에 대해 실행됩니다.
-
==============================
3.포스트 그레스를 사용하는 경우
포스트 그레스를 사용하는 경우
User.limit(5).order("RANDOM()")
MySQL을 사용하는 경우
User.limit(5).order("RAND()")
두 경우 모두 사용자는 사용자 테이블에서 무작위로 5 개 기록을 선택하고 있습니다. 다음은 콘솔에 표시에서 실제 SQL 쿼리입니다.
SELECT * FROM users ORDER BY RANDOM() LIMIT 5
-
==============================
4.나는 더 큰 테이블에 수행하는이 일을 위해 3 보석 레일 체인 관계에 당신을 허용하고 스코프했다 :
나는 더 큰 테이블에 수행하는이 일을 위해 3 보석 레일 체인 관계에 당신을 허용하고 스코프했다 :
https://github.com/spilliton/randumb
(편집) : 내 보석의 기본 동작은 기본적으로 현재 상기와 동일한 방법을 사용하지만, 당신은 당신이 원하는 경우 기존의 방법을 사용할 수있는 옵션이 있습니다 :
-
==============================
5.답변의 대부분은 오히려 큰 테이블 (1 + 백만 행)을 잘 수행하지 않습니다 실제로 기록했다. 임의의 순서는 빠르게 몇 초 정도 소요되며, 테이블에 계산을 수행하는 것은 상당히 오래 걸립니다.
답변의 대부분은 오히려 큰 테이블 (1 + 백만 행)을 잘 수행하지 않습니다 실제로 기록했다. 임의의 순서는 빠르게 몇 초 정도 소요되며, 테이블에 계산을 수행하는 것은 상당히 오래 걸립니다.
이 상황에서 나를 위해 잘 작동하는 솔루션은 어디서 A 조건으로 RANDOM ()를 사용하는 것입니다 :
Thing.where('RANDOM() >= 0.9').take
만 이상의 열이있는 테이블에서이 쿼리는 일반적으로 2ms의 채 걸리지 않습니다.
-
==============================
6.우리가 여기 요
우리가 여기 요
#in your initializer module ActiveRecord class Base def self.random if (c = count) != 0 find(:first, :offset =>rand(c)) end end end end
Model.random #returns single random object
또는 제 생각은
module ActiveRecord class Base def self.random order("RAND()") end end end
용법:
Model.random #returns shuffled collection
-
==============================
7.이 내가 무슨 짓을했는지, 그래서 이것은, 그러나 내가 좀 더 유연성을 필요로 나에게 매우 유용했다 :
이 내가 무슨 짓을했는지, 그래서 이것은, 그러나 내가 좀 더 유연성을 필요로 나에게 매우 유용했다 :
사례 1 : 찾기 한 임의의 레코드 원본 : 트레버 터크 사이트 Thing.rb 모델이 추가
def self.random ids = connection.select_all("SELECT id FROM things") find(ids[rand(ids.length)]["id"].to_i) unless ids.blank? end
다음 컨트롤러에서 당신이 뭔가를 호출 할 수 있습니다
@thing = Thing.random
Case2 : 여러 무작위 기록 (반복없이) 소스를 찾기 : 기억이 안나요 이 내가 일을 찾았는지, 그래서 나는 반복없이 10 개 임의 기록을 찾을 필요 컨트롤러에서 :
thing_ids = Thing.find( :all, :select => 'id' ).map( &:id ) @things = Thing.find( (1..10).map { thing_ids.delete_at( thing_ids.size * rand ) } )
이것은 그러나 그것은 데이터베이스 (기록의 수백만) 특히 큰 경우,이 적합하지 않다고 언급 할 가치이며, 10 개 임의 기록을 찾을 수 및 성능이 방해 될 것입니다. 나를 위해 충분했다 수천 레코드를 잘 수행입니다.
-
==============================
8.무작위로 목록에서 항목을 따기위한 루비 방법은 샘플입니다. 액티브위한 효율적인 샘플을 만들 싶은, 이전 응답에 따라, 내가 사용 :
무작위로 목록에서 항목을 따기위한 루비 방법은 샘플입니다. 액티브위한 효율적인 샘플을 만들 싶은, 이전 응답에 따라, 내가 사용 :
module ActiveRecord class Base def self.sample offset(rand(size)).first end end end
나는이에 lib 디렉토리 / 내선 / sample.rb 다음이에서 설정 / 초기화 / monkey_patches.rb로로드 넣어 :
Dir[Rails.root.join('lib/ext/*.rb')].each { |file| require file }
-
==============================
9.레일 5 작동 및 DB 불가지론이다 :
레일 5 작동 및 DB 불가지론이다 :
컨트롤러에이 :
@quotes = Quote.offset(rand(Quote.count - 3)).limit(3)
다음과 같이 당신은 물론, 관심이 넣을 수 있습니다.
module Randomable extend ActiveSupport::Concern class_methods do def random(the_count = 1) records = offset(rand(count - the_count)).limit(the_count) the_count == 1 ? records.first : records end end end
그때...
class Book < ActiveRecord::Base include Randomable end
그럼 당신은 수행하여 간단하게 사용할 수 있습니다 :
Books.random
또는
Books.random(3)
-
==============================
10.당신은 액티브에 샘플을 ()를 사용할 수 있습니다
당신은 액티브에 샘플을 ()를 사용할 수 있습니다
EG
def get_random_things_for_home_page find(:all).sample(5) end
출처 : http://thinkingeek.com/2011/07/04/easily-select-random-records-rails/
-
==============================
11.오라클을 사용하는 경우
오라클을 사용하는 경우
User.limit(10).order("DBMS_RANDOM.VALUE")
산출
SELECT * FROM users ORDER BY DBMS_RANDOM.VALUE WHERE ROWNUM <= 10
-
==============================
12.강력 특별히 데이터 행이 많은 테이블을 위해 설계 임의 기록이 보석을, 추천 :
강력 특별히 데이터 행이 많은 테이블을 위해 설계 임의 기록이 보석을, 추천 :
https://github.com/haopingfan/quick_random_records
모든 다른 답변이 보석을 제외하고 대형 데이터베이스와 심하게 수행
참고 : 내 테이블은 12 만 사용자를 가지고있다. 당신이 더 많은 기록은 성능의 더 엄청난 차이가있을 것입니다.
최신 정보:
550,000 행이 테이블에 수행
-
==============================
13.아주 쉬운 방법은 테이블에서 여러 무작위 기록을 얻을 수 있습니다. 이것은이 싼 쿼리를합니다.
아주 쉬운 방법은 테이블에서 여러 무작위 기록을 얻을 수 있습니다. 이것은이 싼 쿼리를합니다.
Model.where (ID : Model.pluck (: ID) .sample (3))
당신은 당신이 원하는 임의의 레코드 수에 "3"을 변경할 수 있습니다.
-
==============================
14.난 그냥 내 DB에서 무작위로 질문을 선택하고 싶어 작은 응용 프로그램을 개발하고이 문제에 달렸다. 내가 사용 :
난 그냥 내 DB에서 무작위로 질문을 선택하고 싶어 작은 응용 프로그램을 개발하고이 문제에 달렸다. 내가 사용 :
@question1 = Question.where(:lesson_id => params[:lesson_id]).shuffle[1]
그리고 그것은 나를 위해 잘 작동합니다. 나는이 이후 더 큰 DB에 대한 성능이 단지 작은 응용 프로그램입니다 방법에 대해 말할 수 없다.
from https://stackoverflow.com/questions/5342270/rails-3-get-random-record by cc-by-sa and MIT license
'RUBY-ON-RAILS' 카테고리의 다른 글
[RUBY-ON-RAILS] 레일 : 파셜에 지역 주민을 전달하는 구문에 대해 혼란 (0) | 2020.02.06 |
---|---|
[RUBY-ON-RAILS] 레일의 단수 또는 복수의 컨트롤러 및 도우미 이름 (0) | 2020.02.06 |
[RUBY-ON-RAILS] 어떻게 체인 범위 쿼리에 대한 OR 대신 AND? (0) | 2020.02.06 |
[RUBY-ON-RAILS] Heroku가 배치 오류 H10 (APP 추락) (0) | 2020.02.06 |
[RUBY-ON-RAILS] 레일의 많은 관계로 많은 만들기 (0) | 2020.02.06 |