我在Rails 4应用程序上有一个ruby,使用设计,用户模型和交易模型。
我正在为User和Deal之间的has_many / has_many关系创建一个user_deals
表。
这是迁移
class CreateUserDeals < ActiveRecord::Migration
def change
create_table :user_deals do |t|
t.belongs_to :user
t.belongs_to :deal
t.integer :nb_views
t.timestamps
end
end
end
当用户加载交易时(例如,交易ID = 4),我使用名为show
的方法
controllers/deal.rb
#for the view of the Deal page
def show
end
在此Deal = 4页面的视图中,我需要在用户当前所在的“交易”页面中显示设计current_user
的nb个观看次数
deal/show.html
here is the nb of views of user: <% current_user.#{deal_id}.nb_views%>
允许&#39;说我有10M + user_deals
行,我想知道我是否应该使用索引
add_index :user_deals, :user_id
add_index :user_deals, :deal_id
或者
add_index(:deals, [:user_id, deal_id])
确实在其他情况下我会说是,但在这里我不知道Rails如何在幕后工作。感觉好像Rails在没有我需要加速进程的情况下知道该怎么做,就好像当Rails加载这个视图时没有SQL查询(例如&#39;找到视图的nb WHERe { {1}}和user_id= x
&#39;)....因为我只使用登录的deal_id= Y
(通过设计{{1} }和current_user
Rails知道它,因为我们在这个交易的页面(显示页面),所以我只是将它作为参数传递。
所以我需要一个索引来加速它吗?
答案 0 :(得分:4)
关于索引的问题很好。 Rails 确实生成SQL *以实现其魔力,因此优化数据库的常规规则适用。
设计的魔力只延伸到current_user。它使用SQL查询获取其详细信息,这是有效的,因为默认情况下由devise创建的用户表具有有用的索引。但这些并不是你需要的指标。
首先,有一种更为惯用的方式来做你以后的事情
class CreateUserDeals < ActiveRecord::Migration
def change
create_join_table :users, :deals do |t|
t.integer :nb_views
t.index [:user_id, :deal_id]
t.index [:deal_id, :user_id]
t.timestamps
end
end
end
您会注意到迁移包含两个索引。如果您从未期望为给定的交易创建所有用户的视图,那么您将不再需要这些索引中的第二个。但是,正如@chiptuned所说,索引每个外键几乎总是正确的。整数的索引会花费很少的写入资源,但会大大节省读取费用。这是一个非常低成本的默认防守阵地。
如果您将数据提取逻辑放在控制器中,您将拥有更好的时间并且事情会更加清晰。此外,您正在显示交易,因此您应该做到这一点而不是current_user
获取数据的中心。
您实际上可以在不使用through
关联的情况下执行此查询,因为您可以在不触及users表的情况下执行此操作。 (尽管如此,您可能希望through
关联到其他情况。)
只需has_many :user_deals
即可完成此任务。
为了最好地利用数据库引擎并在一个查询中执行此操作,您的控制器可能如下所示:
def show
@deal = Deal.includes(:user_deals)
.joins(:user_deals)
.where("user_deals.user_id = ?", current_user.id)
.find(params["deal_id"])
end
然后在你看来......
I can get info about the deal: <%= @deal.description %>
感谢includes
我可以在没有单独的SQL查询的情况下获取用户nb_views:
&lt;%= @ deal.user_deals.nb_views%&gt;
*如果你想看看哪些SQL rails神奇地生成了最后只放.to_sql
。例如sql_string = current_user.deals.to_sql
或@deal.to_sql
答案 1 :(得分:1)
是的,您应该使用索引来加速查询user_deals
记录。绝对至少在user_id
上,但可能正如你所说的那样[:user_id, :deal_id]
。
至于为什么你没有看到SQL查询......
首先,视图中的代码似乎不正确。假设您在has_many :deals, through: :user_deals
课程中设置了User
关联,则应该类似于:
here is the nb of views of user: <%= current_user.deals.find(deal_id).nb_views %>
如果您看到显示nb_views
的正确数字,那么在呈现视图时应该进行查询,除非在处理过程中已经加载current_user.deals
或者您已经加载了android-async-http:1.4.9
某种缓存正在进行中。
如果Rails意识到&#34;,那么你应该弄清楚它背后的某种原因。预期的基本Rails行为是在那里发布SQL查询。
答案 2 :(得分:1)
是一种更简洁的方法来索引其他表格:
class CreateUserDeals < ActiveRecord::Migration
def change
create_table :user_deals do |t|
t.references :user
t.references :deal
t.integer :nb_views
t.timestamps
end
end
end