ActiveRecord:大小与计数

And*_*rew 190 ruby ruby-on-rails ruby-on-rails-3 rails-activerecord

在Rails中,您可以找到使用Model.size和的记录数Model.count.如果您正在处理更复杂的查询,那么使用一种方法优于另一种方法是否有任何优势?他们有什么不同?

例如,我有用户的照片.如果我想显示一个用户表和他们有多少张照片,那么运行的实例user.photos.size会更快还是更慢user.photos.count

谢谢!

apn*_*ing 331

你应该读到,它仍然有效.

您将根据需要调整您使用的功能.

基本上:

  • 如果您已经加载了所有条目,User.all那么您应该使用length以避免另一个数据库查询

  • 如果您没有加载任何内容,请使用count对数据库进行计数查询

  • 如果您不想打扰这些考虑因素,请使用size适合的考虑因素

  • 如果`size`无论如何都适应这种情况,那么对于`length`和`count`有什么需要呢? (33认同)
  • 但是,请注意默认大小.例如,如果你创建一个没有经过关系的新记录,即`Comment.create(post_id:post.id)`,你的`post.comments.size`将不是最新的,而`post.comments.count `会的.所以要小心. (33认同)
  • @sscirus - 当你调用`size`(确定要调用哪一个)之后,`size`可以调用它们. (24认同)
  • 此外,如果您通过关系构建多个对象:`company.devices.build(:name =>"device1"); company.devices.build(:name =>"device2")`,然后`company.devices.size`和`.length`将包含你已经构建但尚未保存的对象数,`..count`将仅报告数据库中的计数. (13认同)
  • @sscirrus,size是一个危险的命令,因为它是自动的,有时你确实想要再次查询db. (6认同)
  • 值得一提的是,“count”每次都会发出数据库查询。所以避免在循环内使用它 (2认同)
  • 这个答案可能缺少最新Rails文档(目前是Rails 5.2)中的一些重要信息.[#length](http://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-length)方法将执行`SELECT*...`查询,其中[#size ](http://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-size)方法将执行`SELECT COUNT(*)...`查询.因此,"#size"不再能够"当你不想打扰这些注意事项时",因为它具有与`#length`不同的用例. (2认同)

lim*_*ime 79

正如其他答案所述:

  • count将执行SQL COUNT查询
  • length 将计算结果数组的长度
  • size 将尝试选择最合适的两个,以避免过多的查询

但还有一件事.我们注意到一个size行为不同count/ length完全不同的情况,我想我会分享它,因为它很少被忽视.

  • 如果您:counter_cachehas_many关联上使用a ,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
    
    Run Code Online (Sandbox Code Playgroud)

Rails指南中记录了这种行为,但我要么第一次错过它,要么忘了它.


est*_*ani 9

tl;博士

  • 如果您知道不需要数据,请使用count.
  • 如果您知道您将使用或已经使用该数据,请使用length.
  • 如果您不知道自己在做什么,请使用size...

数数

解决向数据库发送Select count(*)...查询。如果您不需要数据,而只需要计数,那么要走的路。

示例:新消息的计数、仅显示页面时的总元素等。

长度

加载所需的数据,即根据需要进行查询,然后对其进行计数。如果您正在使用数据,则要走的路。

示例:完全加载的表的摘要、显示数据的标题等。

尺寸

它检查数据是否已加载(即已经在 Rails 中),如果是,则对其进行计数,否则调用计数。(加上其他条目中已经提到的陷阱)。

def size
  loaded? ? @records.length : count(:all)
end
Run Code Online (Sandbox Code Playgroud)

有什么问题?

如果您没有按照正确的顺序进行操作,您可能会两次访问数据库(例如,如果您在渲染表的顶部渲染表中的元素数量,则实际上将有 2 次调用发送到数据库)。


jva*_*nen 7

有时size"选错了"并返回一个哈希(这是count做什么的)

在这种情况下,使用length获取整数而不是哈希.