it-swarm.com.ru

ActiveRecord: размер против количества

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

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

Спасибо!

185
Andrew

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

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

В принципе:

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

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

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

319
apneadiving

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

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

77
lime

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

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

7
jvalanen

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

Model.count

Model.all.size

records = Model.all
records.count

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

records = Model.all
records.size

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

3
Dennis

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

class Customer < ActiveRecord::Base
  has_many :customer_activities
end

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

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

Если вы используете: counter_cache для ассоциации has_many, 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 - лучший вариант для расчета количества записей.

1
manthan andharia