我有3个模型,投资组合,股票和交易。当我在投资组合展示页面时,我会遍历投资组合的交易并绘制股票以显示我买的东西。
当我加载投资组合显示页面时,日志看起来像这样:
Started GET "/portfolios/1" for ::1 at 2016-09-24 02:15:32 -0400
Processing by PortfoliosController#show as HTML
Parameters: {"id"=>"1"}
Portfolio Load (0.6ms) SELECT "portfolios".* FROM "portfolios"
WHERE "portfolios"."id" = $1 LIMIT 1 [["id", 1]]
Transaction Load (2.0ms) SELECT "transactions".* FROM "transactions"
WHERE "transactions"."portfolio_id" = $1 [["portfolio_id", 1]]
Stock Load (1.7ms) SELECT "stocks".* FROM "stocks" WHERE "stocks"."id" = $1 LIMIT 1 [["id", 1]]
Stock Load (0.2ms) SELECT "stocks".* FROM "stocks" WHERE "stocks"."id" = $1 LIMIT 1 [["id", 6]]
Stock Load (0.2ms) SELECT "stocks".* FROM "stocks" WHERE "stocks"."id" = $1 LIMIT 1 [["id", 4]]
CACHE (0.0ms) SELECT "stocks".* FROM "stocks" WHERE "stocks"."id" = $1 LIMIT 1 [["id", 6]]
Stock Load (0.2ms) SELECT "stocks".* FROM "stocks" WHERE "stocks"."id" = $1 LIMIT 1 [["id", 2]]
Stock Load (0.2ms) SELECT "stocks".* FROM "stocks" WHERE "stocks"."id" = $1 LIMIT 1 [["id", 13]]
Stock Load (0.2ms) SELECT "stocks".* FROM "stocks" WHERE "stocks"."id" = $1 LIMIT 1 [["id", 9]]
Stock Load (0.2ms) SELECT "stocks".* FROM "stocks" WHERE "stocks"."id" = $1 LIMIT 1 [["id", 16]]
Stock Load (0.3ms) SELECT "stocks".* FROM "stocks"
Rendered transactions/_form.html.erb (19.1ms)
Rendered portfolios/show.html.erb within layouts/application (69.6ms)
Rendered application/_nav.html.erb (0.4ms)
Completed 200 OK in 128ms (Views: 90.5ms | ActiveRecord: 9.2ms)
我的交易,股票和投资组合模型都有这些关联:
class Transaction < ActiveRecord::Base
belongs_to :portfolio
belongs_to :stock
end
class Stock < ActiveRecord::Base
has_many :transactions
end
class Portfolio < ActiveRecord::Base
belongs_to :user
has_many :transactions
has_many :stocks, through: :transactions
end
在展示页面中,我循环浏览实例组合,并使用.each来获取相关股票。
<% @portfolio.transactions.each do |trade| %>
在投资组合控制器中,@ portfolio被定义为@portfolio = Portfolio.find(params [:id])。
是否有更有效的方法来查询数据库(postgres)以检索关联的库存对象。现在这不是一个问题,但我在考虑人们有多年的投资组合,并且在投资组合中有数百个交易。或者我应该考虑使用memcache或redis缓存特定投资组合页面的结果?
答案 0 :(得分:0)
要避免这些查询,您需要预加载关联 像这样的东西
@portfolio = Portfolio.preload(:stocks).find(params[:id])
答案 1 :(得分:0)
这看起来像N + 1 queries problem,您可以使用Queue
或eager_load
或preload
来摆脱它:
includes
答案 2 :(得分:0)
我将我的@portfolio对象重新编写为@portfolio = Portfolio.includes(:transactions,:stocks).find(params [:id])。 现在我一批获得所有股票。
Parameters: {"id"=>"1"}
Portfolio Load (0.3ms) SELECT "portfolios".* FROM "portfolios"
WHERE "portfolios"."id" = $1 LIMIT 1 [["id", 1]]
Transaction Load (0.5ms) SELECT "transactions".* FROM "transactions"
WHERE "transactions"."portfolio_id" IN (1)
Stock Load (0.4ms) SELECT "stocks".* FROM "stocks" WHERE
"stocks"."id" IN (1, 6, 4, 2, 13, 9, 16)
Stock Load (0.3ms) SELECT "stocks".* FROM "stocks"
这就是我想要的。由于我使用的是Rails 5,我不确定eager_load或preload方法是否会降级。包含似乎是一个更稳定的选择。