急切加载 Paperclip 的 has_attached_file 数据?
Product has_many :assets
Asset own_to :product
Asset has_attached_file :photo
使用回形针(包含所有标准回形针选项;一些样式、S3 存储) 。
如果我形成像 p = Product.includes(:assets)
这样的 Product 查询,我可以调用 Asset 的每个实际属性,而不会产生任何额外的数据库查询,例如:
p = Product.includes(:assets)
p.each { |a| print a.assets.first.title }
title
Asset(这是一个数据库列)上的 > 属性打印,不进行任何查询。
要获取由 Paperclip 生成的网址:
p = Product.includes(:assets)
p.each { |a| print a.assets.first.photo.url }
会对每个 Product
进行单独的附加查询:
Product Load (0.3ms) SELECT "products".* FROM "products" WHERE "products"."id" = 2 LIMIT 1
根据 这个 G.Groups 帖子,我不应该在每次循环时都访问数据库,但我确实这样做了。
有没有一种方法可以避免每次迭代产生额外的数据库命中,而是一次性收集所有数据?我是否忽略了一些简单的事情?
Rails 3.0.9、REE 1.8.7、回形针 2.3.11。
已更新,已修复
问题是在我的回形针设置中,我将 :product_id
作为 :path
的一部分::attachment/ :product_id/:filename-:style.:extension
,这会导致循环中每次迭代进行额外的 Product 查询。
通过将查询更改为 p = Product.includes(:assets => [:product]).all
,它删除了附加查询。
Product has_many :assets
Asset belongs_to :product
Asset has_attached_file :photo
using Paperclip (with all your standard Paperclip options; a few styles, S3 storage).
If I form a Product query like p = Product.includes(:assets)
I can call each of the actual attributes of Asset without incurring any additional database queries, like:
p = Product.includes(:assets)
p.each { |a| print a.assets.first.title }
The title
attribute on Asset
(which is a database column) prints, no queries made.
To get the URL generated by Paperclip:
p = Product.includes(:assets)
p.each { |a| print a.assets.first.photo.url }
causes a separate additional query for each Product
:
Product Load (0.3ms) SELECT "products".* FROM "products" WHERE "products"."id" = 2 LIMIT 1
According to this G.Groups posting, I shouldn't be hitting the database with each pass through the loop, but I am.
Is there a way to not incur the additional database hit for each iteration, but gather all the data all at once? Am I overlooking something simple?
Rails 3.0.9, REE 1.8.7, Paperclip 2.3.11.
updated, fixed
The issue is that in my Paperclip settings, I have :product_id
as part of the :path
: :attachment/:product_id/:filename-:style.:extension
, which is causing the additional Product query for each iteration through the loop.
By changing the query to p = Product.includes(:assets => [:product]).all
, it removed the additional query.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您使用查询分析器插件之一尝试查询审查器,或者如果您使用 newrelic,那么我们可以更快地找到问题的根源,开发模式包括此功能。您将获得每个查询的堆栈跟踪。我不认为它与急切加载有任何关系 - 如果确实如此,您将获得额外的资产加载而不是产品加载。
We can get to the root of the problem much faster if you use one of the query analyzer plugins Try query-reviewer, or if you're using newrelic, the dev mode includes this. You'll get a stack trace for every query. I don't think it has anything to do with eager loading - if it did, you'd be getting extra Asset loads instead of Product loads.
我认为您忽略了一些简单的事情:
includes
设置关系以立即加载关联,all
执行实际查询。I think you're overlooking something simple:
includes
sets the relation to eager load the association,all
does the actual query.