在Rails中,您可以找到同时使用Model.size
和Model.count
的记录数。如果您正在处理更复杂的查询,那么使用一种方法优于另一种方法是否有任何优势?他们有什么不同?
例如,我有用户提供照片。如果我想要显示用户的表格以及他们拥有的照片数量,那么user.photos.size
的许多实例会比user.photos.count
更快还是更慢?
谢谢!
答案 0 :(得分:318)
您应该阅读that,它仍然有效。
您可以根据需要调整使用的功能。
基本上:
如果你已经加载了所有条目,比如User.all
,那么你应该使用length
来避免另一个数据库查询
如果您没有加载任何内容,请使用count
对您的数据库进行计数查询
如果您不想打扰这些注意事项,请使用适合的size
答案 1 :(得分:77)
正如其他答案所述:
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
the Rails Guides中记录了此行为,但我第一次错过了或忘了它。
答案 2 :(得分:7)
有时size
“选错了”并返回哈希(这是count
会做的事情)
在这种情况下,请使用length
获取整数,而不是哈希。
答案 3 :(得分:3)
以下策略都会调用数据库来执行COUNT(*)
查询。
Model.count
Model.all.size
records = Model.all
records.count
以下效率不如将数据库中的所有记录加载到Ruby中,后者会计算集合的大小。
records = Model.all
records.size
如果模型具有关联并且您想要查找所属对象的数量(例如@customer.orders.size
),则可以避免数据库查询(磁盘读取)。使用counter cache和Rails将使缓存值保持最新,并返回该值以响应size
方法。
答案 4 :(得分:0)
我建议使用尺寸功能。
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是计算记录数的最佳选择。
答案 5 :(得分:0)
count
。length
。size
... 解决向数据库发送Select count(*)...
查询的问题。如果您不需要数据,而只需计数,该怎么办。
示例:新消息的计数,仅将要显示页面时的元素总数等。
加载所需的数据(即根据需要的查询),然后对其进行计数。使用数据的方式。
示例:已满载表格的摘要,显示数据的标题等
它会检查是否已加载数据(即已经在轨道中),然后对其进行计数,否则调用count。 (加上其他条目已经提到的陷阱)。
def size
loaded? ? @records.length : count(:all)
end
出什么问题了?
如果您未按正确的顺序进行操作,您可能会两次访问数据库(例如,如果您在呈现的表顶部呈现表中的元素数量,那么实际上将有2个调用发送到DB)。