2014-06-25 2 views
1

ID의 배열이 있다고 가정 해 봅시다. 어쩌면 약 100000 개의 ID가 있다고 가정합니다. 이 경우 임시 테이블을 만들어 JOIN을 할 수 없습니다. 이 배열이 큰 경우 MySQL의 상처를 보인다 WHERE IN 절을 생성합니다ID 목록에서 더 나은 솔루션을 찾으십니까?

Product.where(id: ids) 

: 나를 위해 간단한 해결책하는 것입니다. 이보다 더 좋은 해결책이 있을까?

답변

5

연속 범위라면 BETWEEN - Product.where id: 1..100000을 사용해보세요.

그렇지 않으면 whole_array_of_ids.each_slice(number_of_ids_mysql_can_handle){ |ids| Product.where(id: ids) } - 여러 개의 쿼리가 있지만 관리가 가능합니다. Read about each_slice and more goodies here.

또한 많은 AR 찾기 메서드에는 batch_size 매개 변수가 있지만 여기에는 모든 ID로 전체 쿼리를 구성한 다음 끝에 LIMIT을 붙이면 도움이되지 않는 것 같습니다.

+1

내 프로젝트 중 하나에서는 between 메서드를 사용합니다. 배열의 범위를 얻으려면 https://gist.github.com/Bjoernsen/b38cc5cde2b2c6fc3a0d – Bjoernsen

+0

을 보내 주셔서 감사합니다. 답변을 주셔서 감사합니다. 그러나 ID는 연속 범위가 아니지만 무작위입니다. – Frozenna

2

find_each를 사용하면 한 번에로드 할 레코드 수를 제한 할 수 있습니다. 1000 개 레코드를 한 번에로드 기본값을 find_each,하지만 당신은 설정하여 있음을 조정할 수 있습니다 BATCH_SIZE 옵션 :

이 한 번에 1,000 기록에 대한 데이터베이스를 조회합니다 :

Product.where(id: ids).find_each do |product| 
    # do something with the product 
end 

아니면을 변경할 수 있습니다 한 번에로드 된 레코드 수 (약 50?) :

Product.where(id: ids).find_each(batch_size: 50) do |product| 
    # do something with the product 
end 
+1

IN 절에 많은 수의 ID를 넣을 때 이들 중 어느 것도 도움이되지 않습니다. 'select * from posts where id (1,2,3, ..., 1234567890)'와 같은 질의가 있으면 데이터베이스는 select 자체를 실행하는 것을 막습니다. 예를 들어, Oracle은 IN 절에서 1000 개의 항목을 엄격하게 제한했습니다. 다른 사람들은 몇 천 개가 넘는 아이템으로는 참을 수 없을 정도로 느려지 게 될 것입니다. –