[RUBY-ON-RAILS] 사용 중단 경고 : 위험한 쿼리 방법 :> = 5.2 액티브에서 임의의 기록
RUBY-ON-RAILS사용 중단 경고 : 위험한 쿼리 방법 :> = 5.2 액티브에서 임의의 기록
지금까지 데이터베이스에서 임의의 기록을 얻을 수있는 "일반적인"방법이있다 :
# Postgress
Model.order("RANDOM()").first
# MySQL
Model.order("RAND()").first
레일 5.2에서이 일 때, 다음과 같은 사용 중단 경고를 보여줍니다
나는 Arel 정말 익숙하지 않다, 그래서 나는 반드시이 문제를 해결하는 올바른 방법 일 것입니다 무슨 아닙니다.
해결법
-
==============================
1.당신에 의해 주문을 계속 사용하려는 경우) (랜덤 후 바로 사용 중단 경고가 제안처럼 Arel.sql에 포장하여 안전 선언
당신에 의해 주문을 계속 사용하려는 경우) (랜덤 후 바로 사용 중단 경고가 제안처럼 Arel.sql에 포장하여 안전 선언
Model.order(Arel.sql('random()')).first
임의의 행을 선택하고 그들은 모두 장점과 단점을 가지고하는 방법이 많이 있습니다하지만 그런 당신이 루비의 배열과 일치해야 할 순서를 필요로 할 때와 같이 절대적으로 순서대로 SQL의 조각을 사용해야 번 (있다 Arel.sql를 사용하여 주위를 얻을 수 있도록 데이터베이스에 이르기까지 엔드 표현)이 제한 도구에 대해 알아야 할 우리 모두 필요하다 "속성 만"때 ... 큰 경우를 얻을.
편집 됨 : 샘플 코드는 닫는 괄호가 없습니다.
-
==============================
2.나는이 솔루션의 팬입니다 :
나는이 솔루션의 팬입니다 :
Model.offset(rand(Model.count)).first
-
==============================
3.많은 레코드, 그리고 많은하지 삭제 된 레코드로,이보다 효율적으로 할 수있다. 기본 범위는 조인을 사용하기 때문에 내 경우에는 내가 .unscoped 사용해야합니다. 모델 같은 기본 범위를 사용하지 않는 경우, 당신은이 나타나는 곳마다이 .unscoped 생략 할 수 있습니다.
많은 레코드, 그리고 많은하지 삭제 된 레코드로,이보다 효율적으로 할 수있다. 기본 범위는 조인을 사용하기 때문에 내 경우에는 내가 .unscoped 사용해야합니다. 모델 같은 기본 범위를 사용하지 않는 경우, 당신은이 나타나는 곳마다이 .unscoped 생략 할 수 있습니다.
Patient.unscoped.count #=> 134049 class Patient def self.random return nil unless Patient.unscoped.any? until @patient do @patient = Patient.unscoped.find rand(Patient.unscoped.last.id) end @patient end end #Compare with other solutions offered here in my use case puts Benchmark.measure{10.times{Patient.unscoped.order(Arel.sql('RANDOM()')).first }} #=>0.010000 0.000000 0.010000 ( 1.222340) Patient.unscoped.order(Arel.sql('RANDOM()')).first Patient Load (121.1ms) SELECT "patients".* FROM "patients" ORDER BY RANDOM() LIMIT 1 puts Benchmark.measure {10.times {Patient.unscoped.offset(rand(Patient.unscoped.count)).first }} #=>0.020000 0.000000 0.020000 ( 0.318977) Patient.unscoped.offset(rand(Patient.unscoped.count)).first (11.7ms) SELECT COUNT(*) FROM "patients" Patient Load (33.4ms) SELECT "patients".* FROM "patients" ORDER BY "patients"."id" ASC LIMIT 1 OFFSET 106284 puts Benchmark.measure{10.times{Patient.random}} #=>0.010000 0.000000 0.010000 ( 0.148306) Patient.random (14.8ms) SELECT COUNT(*) FROM "patients" #also Patient.unscoped.find rand(Patient.unscoped.last.id) Patient Load (0.3ms) SELECT "patients".* FROM "patients" ORDER BY "patients"."id" DESC LIMIT 1 Patient Load (0.4ms) SELECT "patients".* FROM "patients" WHERE "patients"."id" = $1 LIMIT 1 [["id", 4511]]
우리가 임의의 ID를 얻을 단지 하나의 레코드에 발견 할 랜드 ()를 사용하고 있기 때문에 이것에 대한 이유입니다. 그러나 더 큰 삭제 행수 일수록 while 루프가 여러 번 실행된다 (ID를 생략). 그것은 잔인한 수도 있지만 62 %의 성능 증가 및 더 높은 경우는 결코 삭제 행 가치가있을 수 있습니다. 테스트는 사용 사례에 대한 더 나은 경우.
from https://stackoverflow.com/questions/48897070/deprecation-warning-dangerous-query-method-random-record-in-activerecord-5 by cc-by-sa and MIT license
'RUBY-ON-RAILS' 카테고리의 다른 글
[RUBY-ON-RAILS] 단일 페이지 응용 프로그램 및 CSRF 토큰 (0) | 2020.02.26 |
---|---|
[RUBY-ON-RAILS] 왜 루비 온 레일즈는 "음이 배열 'ruby_check_sizeof_voidp'의 크기"오류가 발생 설치합니까? (0) | 2020.02.26 |
[RUBY-ON-RAILS] has_many를 들어 범위 지정을 레일 :에 대한 액세스 추가 데이터를 통해 (0) | 2020.02.26 |
[RUBY-ON-RAILS] 어떻게 Heroku가에 레일 응용 프로그램을 배포하기 위해이 문제를 해결할 수 있습니까? (0) | 2020.02.26 |
[RUBY-ON-RAILS] 서버를 시작할 때 세그먼트 오류를 레일? (0) | 2020.02.26 |