我有一个Rails命令:
Product.includes(:sale, :product_description).select('distinct on (size) *')
据我了解,当我运行此命令时,Rails会急切地将结果加载到内存中,并且由于只有4种大小,因此结果应仅包含4条记录。但是,如果我做类似的事情:
result = Product.includes(:sale, :product_description).select('distinct on (size) *')
,然后执行:result.size
。结果将是所有产品记录的计数,即435。但是,如果我这样做:result.length
,我将得到预期的响应,即4。
为什么length
和size
的结果不同?我以为通过使用includes
会热切加载所有内容,因此length
和size
应该返回相同的计数?
还请注意,如果我先运行length
,然后再运行size
,两者都返回正确的结果4。但是,如果我先运行size
,则得到的错误响应为435。
答案 0 :(得分:2)
count
上的size
,length
和ActiveRecord::Relations
之间存在细微差别(有关详细信息,请参见this answer)
在您的示例中,length
将始终执行与ActiveRecord::Relation
相同的确切查询,然后在返回的数组上调用length
。
而result.size
将在之前未加载count
时执行ActiveRecord::Relation
查询。由于count
返回数字(而不是实际记录),因此查询得到了优化,并且include
和select
部分被忽略。从性能的角度来看,这是有道理的。
但是如果Relation
已经被加载(例如,当您在length
之前调用size
),那么size
只会返回已经加载的数组的大小。 / p>