ActiveRecord : 크기 대 개수


201

레일에서는 모두 사용하여 레코드의 수를 찾을 수 Model.sizeModel.count. 더 복잡한 쿼리를 처리하는 경우 한 방법을 다른 방법보다 사용하는 것이 유리합니까? 그것들은 어떻게 다릅니 까?

예를 들어 사진이있는 사용자가 있습니다. 사용자 테이블과 사용자가 보유한 사진 수를 표시하려면 많은 인스턴스를 실행하는 user.photos.size것이보다 빠르거나 느려 user.photos.count집니까?

감사!

답변:


344

당신은 읽어야 것을 여전히 유효입니다.

필요에 따라 사용하는 기능을 조정합니다.

원래:

  • 이미 모든 항목을로드하는 경우 (예 User.all: length다른 DB 쿼리를 피하기 위해 사용해야 함)

  • 아무것도로드하지 않은 경우을 사용 count하여 DB에서 개수 쿼리를하십시오.

  • 이러한 고려 사항에 신경 쓰지 않으려면 사용할 size것을 사용하십시오.


35
경우 size어쨌든 상황에 적응하고 무엇을 필요로하기 위해 존재 lengthcount전혀?
sscirrus

27
@sscirus- size전화를 걸 때 size( 전화 할 전화를 결정한 후) 전화를 걸 수 있습니다.
Batkins

35
그러나 크기를 기본값으로 설정하는 데주의하십시오. 예를 들어, 당신은 즉, 관계를 거치지 않고 새 레코드를 만들 경우 Comment.create(post_id: post.id)당신, post.comments.size동안 의지는 최신이 아닐 post.comments.count것입니다. 그러니 조심하세요
mrbrdo

14
당신이 관계를 통해 여러 개체를 만들 경우에도 : company.devices.build(:name => "device1"); company.devices.build(:name => "device2")다음 company.devices.size.length당신이 구축했지만 저장하지 않은 개체의 수를 포함 .count데이터베이스에서 단지 수를보고합니다.
Shawn J. Goff

6
@ sscirrus, size는 자동화되어 있기 때문에 위험한 명령입니다. 때로는 db를 다시 쿼리하고 싶을 수도 있습니다.
Alex C

79

다른 답변은 다음과 같이 말합니다.

  • countSQL COUNT쿼리 를 수행 합니다
  • length 결과 배열의 길이를 계산합니다
  • size 과도한 쿼리를 피하기 위해 둘 중 가장 적절한 것을 선택하려고합니다.

그러나 한 가지 더 있습니다. 우리는 완전히 / size다르게 행동 하는 경우를 발견했으며 간과하기가 드물기 때문에 그것을 공유 할 것이라고 생각했습니다.countlength

  • 당신은을 사용하는 경우 :counter_cacheA의 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 에 설명되어 있지만 처음 놓쳤거나 잊어 버렸습니다.


실제로 레일 5.0.0.beta1 이전에는 _count열 이 있어도 ( counter_cache: true연결에 대한 지시어가 없는 경우)이 동작이 트리거됩니다 . 이것은 github.com/rails/rails/commit/e0cb21f5f7
cbliard

8

때로는 size반환은 "잘못된 선택합니다" 해시 (무엇을 count할 것을)

이 경우 hash 대신 정수length 를 얻는 데 사용하십시오 .


has_many 인스턴스의 Collection에서 '.size'를 사용했으며 컬렉션에 하나의 레코드가 있었지만 size는 '0'을 반환했습니다. .count를 사용하면 올바른 값 '1'이 반환되었습니다.
admazzola

4

tl; dr

  • 데이터 사용이 필요하지 않다는 것을 알고 있다면 count.
  • 데이터 사용을 사용하거나 사용한 것을 알고있는 경우 length.
  • 당신이하고있는 일을 모른다면, 사용하십시오 size...

카운트

Select count(*)...쿼리를 DB 로 전송합니다 . 데이터가 필요하지 않고 카운트 만 있으면 갈 수 있습니다.

예 : 새 메시지 수, 페이지 만 표시 될 때의 총 요소 수 등

길이

필요한 데이터, 즉 필요에 따라 쿼리를로드 한 다음 계산합니다. 데이터를 사용하는 경우 갈 길.

예 : 완전히로드 된 테이블 요약, 표시된 데이터 제목 등

크기

데이터가로드되었는지 (즉, 이미 레일에)로드되어 있는지 확인한 다음 카운트 만하고 그렇지 않으면 count를 호출합니다. (다른 항목에서 이미 언급 한 함정).

def size
  loaded? ? @records.length : count(:all)
end

뭐가 문제 야?

올바른 순서로 수행하지 않으면 DB를 두 번 누르게 될 수 있습니다 (예 : 렌더링 된 테이블 위에 테이블의 요소 수를 렌더링하는 경우 실제로 DB에 2 개의 호출이 전송 됨).


3

다음 전략은 모두 데이터베이스를 호출하여 COUNT(*)쿼리 를 수행 합니다.

Model.count

Model.all.size

records = Model.all
records.count

다음은 데이터베이스의 모든 레코드를 Ruby로로드하는 것만 큼 효율적이지 않으며, 컬렉션의 크기를 계산합니다.

records = Model.all
records.size

모델에 연결이 있고 소속 개체 수 (예 :)를 찾으려면 @customer.orders.size데이터베이스 쿼리 (디스크 읽기)를 피할 수 있습니다. 카운터 캐시를 사용하면 Rails는 캐시 값을 최신 상태로 유지하고 size메소드 에 대한 응답으로 해당 값을 반환합니다 .


2
모두 Model.all.sizeModel.all.count생성 count레일 4 위의 쿼리를. 실제 장점은 size연결이 이미로드 된 경우 개수 쿼리를 생성하지 않는다는 것입니다. Rails 3 이하에서는 Model.all관계가 없다고 생각 하므로 모든 레코드가 이미로드되었습니다. 이 답변이 오래되었을 수 있으므로 삭제하는 것이 좋습니다.
Damon Aw

1

크기 기능을 사용하는 것이 좋습니다.

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를 사용하는 것이 레코드 수를 계산하는 가장 좋은 옵션이라는 것을 알았습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.