레일에서는 모두 사용하여 레코드의 수를 찾을 수 Model.size
및 Model.count
. 더 복잡한 쿼리를 처리하는 경우 한 방법을 다른 방법보다 사용하는 것이 유리합니까? 그것들은 어떻게 다릅니 까?
예를 들어 사진이있는 사용자가 있습니다. 사용자 테이블과 사용자가 보유한 사진 수를 표시하려면 많은 인스턴스를 실행하는 user.photos.size
것이보다 빠르거나 느려 user.photos.count
집니까?
감사!
답변
당신은 읽어야 것을 여전히 유효입니다.
필요에 따라 사용하는 기능을 조정합니다.
원래:
-
이미 모든 항목을로드하는 경우 (예
User.all
:length
다른 DB 쿼리를 피하기 위해 사용해야 함) -
아무것도로드하지 않은 경우을 사용
count
하여 DB에서 개수 쿼리를하십시오. -
이러한 고려 사항에 신경 쓰지 않으려면 사용할
size
것을 사용하십시오.
답변
다른 답변은 다음과 같이 말합니다.
count
SQLCOUNT
쿼리 를 수행 합니다length
결과 배열의 길이를 계산합니다size
과도한 쿼리를 피하기 위해 둘 중 가장 적절한 것을 선택하려고합니다.
그러나 한 가지 더 있습니다. 우리는 완전히 / size
다르게 행동 하는 경우를 발견했으며 간과하기가 드물기 때문에 그것을 공유 할 것이라고 생각했습니다.count
length
-
당신은을 사용하는 경우
:counter_cache
A의has_many
연결,size
직접 계산 캐시 된을 사용하고, 전혀 추가 질의를하지 않습니다.class Image < ActiveRecord::Base belongs_to :product, counter_cache: true end class Product < ActiveRecord::Base has_many :images end > product = Product.first # query, load product into memory > product.images.size # no query, reads the :images_count column > product.images.count # query, SQL COUNT > product.images.length # query, loads images into memory
이 동작은 Rails Guides 에 설명되어 있지만 처음 놓쳤거나 잊어 버렸습니다.
답변
때로는 size
반환은 “잘못된 선택합니다” 해시 (무엇을 count
할 것을)
이 경우 hash 대신 정수length
를 얻는 데 사용하십시오 .
답변
tl; dr
- 데이터 사용이 필요하지 않다는 것을 알고 있다면
count
. - 데이터 사용을 사용하거나 사용한 것을 알고있는 경우
length
. - 당신이하고있는 일을 모른다면, 사용하십시오
size
…
카운트
Select count(*)...
쿼리를 DB 로 전송합니다 . 데이터가 필요하지 않고 카운트 만 있으면 갈 수 있습니다.
예 : 새 메시지 수, 페이지 만 표시 될 때의 총 요소 수 등
길이
필요한 데이터, 즉 필요에 따라 쿼리를로드 한 다음 계산합니다. 데이터를 사용하는 경우 갈 길.
예 : 완전히로드 된 테이블 요약, 표시된 데이터 제목 등
크기
데이터가로드되었는지 (즉, 이미 레일에)로드되어 있는지 확인한 다음 카운트 만하고 그렇지 않으면 count를 호출합니다. (다른 항목에서 이미 언급 한 함정).
def size
loaded? ? @records.length : count(:all)
end
뭐가 문제 야?
올바른 순서로 수행하지 않으면 DB를 두 번 누르게 될 수 있습니다 (예 : 렌더링 된 테이블 위에 테이블의 요소 수를 렌더링하는 경우 실제로 DB에 2 개의 호출이 전송 됨).
답변
다음 전략은 모두 데이터베이스를 호출하여 COUNT(*)
쿼리 를 수행 합니다.
Model.count
Model.all.size
records = Model.all
records.count
다음은 데이터베이스의 모든 레코드를 Ruby로로드하는 것만 큼 효율적이지 않으며, 컬렉션의 크기를 계산합니다.
records = Model.all
records.size
모델에 연결이 있고 소속 개체 수 (예 :)를 찾으려면 @customer.orders.size
데이터베이스 쿼리 (디스크 읽기)를 피할 수 있습니다. 카운터 캐시를 사용하면 Rails는 캐시 값을 최신 상태로 유지하고 size
메소드 에 대한 응답으로 해당 값을 반환합니다 .
답변
크기 기능을 사용하는 것이 좋습니다.
class Customer < ActiveRecord::Base
has_many :customer_activities
end
class CustomerActivity < ActiveRecord::Base
belongs_to :customer, counter_cache: true
end
이 두 모델을 고려하십시오. 고객에게 많은 고객 활동이 있습니다.
has_many 연관에서 : counter_cache를 사용하면 size는 캐시 된 수를 직접 사용하고 추가 쿼리를 전혀하지 않습니다.
한 가지 예를 생각해보십시오. 데이터베이스에서 한 고객은 20,000 개의 고객 활동을 가지고 있으며 각 고객 수, 길이 및 크기 방법으로 해당 고객의 고객 활동 레코드 수를 세려고합니다. 이 모든 방법의 벤치 마크 보고서 아래에 있습니다.
user system total real
Count: 0.000000 0.000000 0.000000 ( 0.006105)
Size: 0.010000 0.000000 0.010000 ( 0.003797)
Length: 0.030000 0.000000 0.030000 ( 0.026481)
그래서 : counter_cache Size를 사용하는 것이 레코드 수를 계산하는 가장 좋은 옵션이라는 것을 알았습니다.