ActiveRecord: размер против количества - PullRequest
188 голосов
/ 21 мая 2011

В Rails вы можете найти количество записей, используя Model.size и Model.count.Если вы имеете дело с более сложными запросами, есть ли преимущество в использовании одного метода перед другим?Чем они отличаются?

Например, у меня есть пользователи с фотографиями.Если я хочу показать таблицу пользователей и сколько у них фотографий, будет ли запускать много экземпляров user.photos.size быстрее или медленнее, чем user.photos.count?

Спасибо!

Ответы [ 5 ]

323 голосов
/ 21 мая 2011

Вы должны прочитать , что , оно все еще действует.

Вы адаптируете используемую функцию в зависимости от своих потребностей.

В основном:

  • если вы уже загрузили все записи, скажем, User.all, тогда вам следует использовать length, чтобы избежать другого запроса БД

  • если у вас ничего не загружено, используйте count, чтобы сделать запрос подсчета для вашей базы данных

  • , если вы не хотите беспокоиться об этих соображениях, используйте size, который адаптирует

79 голосов
/ 07 февраля 2014

Поскольку другие ответы указывают:

  • count выполнит запрос SQL COUNT
  • length вычислит длину результирующего массива
  • size попытается выбрать наиболее подходящий из двух, чтобы избежать чрезмерных запросов

Но есть еще одна вещь.Мы заметили случай, когда size действует иначе, чем count / length, и я подумал, что поделюсь им, так как это достаточно редко, чтобы его упустить из виду.

  • Есливы используете :counter_cache для ассоциации 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 , но я либо пропустил его в первый раз, либо забыл об этом.

7 голосов
/ 28 января 2015

Иногда size "выбирает неправильный" и возвращает хеш (что и делает count)

В этом случае используйте length, чтобы получить целое число вместо хэш .

3 голосов
/ 01 февраля 2014

Все следующие стратегии обращаются к базе данных для выполнения запроса COUNT(*).

Model.count

Model.all.size

records = Model.all
records.count

Следующее не так эффективно, так как оно загружает все записи из базы данных в Ruby, который затем подсчитывает размер коллекции.

records = Model.all
records.size

Если ваши модели имеют ассоциации, и вы хотите узнать количество принадлежащих объектов (например, @customer.orders.size), вы можете избежать запросов к базе данных (чтение с диска). Используйте счетчик кеша , и Rails будет обновлять значение кеша и возвращать это значение в ответ на метод size.

1 голос
/ 15 марта 2019

Я рекомендовал использовать функцию размера.

class Customer < ActiveRecord::Base
  has_many :customer_activities
end

class CustomerActivity < ActiveRecord::Base
  belongs_to :customer, counter_cache: true
end

Рассмотрим эти две модели.У клиента есть много действий клиента.

Если вы используете: counter_cache для ассоциации has_many, размер будет напрямую использовать кэшированный счетчик, и вообще не будет делать дополнительный запрос.

Рассмотрим один примерВ моей базе данных один клиент имеет 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 - лучший вариант для расчета количества записей.

...