2011-12-19 94 views
2

我正在与很大的mysql2数据库在此刻工作了很多,虽然我已经索引了我认为是合适的字段,但某些查询的返回时间非常缓慢。Rails数据库性能调优

我有两个型号导致问题,CommentCommenter

现在,CommenterComment之间存在has_many关系,但我的查询依赖于查找每个评论的评论者的用户名。所以,我会跑是这样的:

c = Blog.first.comments ##this bit runs fine, I indexed the "blog_id" field on Comments 
c.collect {|c| c.commenter.username} 

为了帮助与速度问题,我创建了用于评价模型commenter_id领域的指标。但它仍然运行非常缓慢..

有人知道我可以做什么不同,这将有助于提高查询的速度?

回答

0

我想通了用渴望的负载,这是不RaskolnikOFF发布的链接,但在此之前它的轨道铸造,http://railscasts.com/episodes/22-eager-loading(还是给你一个给予好评的驾驶我的答案)

显然我正在寻找的是以下内容:

b = Blog.find(:first, :include=>{:comments => :commenter}) 
b.comments.collect {|c| c.commenter.username} 

第一行加载第一个博客及其所有关系(并返回博客)。所以当我打电话给第二条线时,一切都已经加载并且正在等待被访问..

这比我原本做的更好。

3

commenter_id上的索引有助于您在查找给定的commenter_id(“找到我所有的评论joe made”)的评论。

但是当你做c.commenter你正在寻找的用户,可能是id等于评论的commenter_id的用户。应该已经有id列的索引。在正确的方式是采取实际生成的SQL语句(在发展这些都是development.log),并利用他们解释,例如

explain select * from comments where id = 12345 

鉴于这是非常不可能的,你成功地创建一个表而不它的指数是id列,最有可能的罪魁祸首是预先加载 - 如果一个职位有500个评论,那么上面的代码将获取相关联的用户一个接一个,和那些500次往返于数据库中添加了

c.includes(:commenter).collect {...} 

c.eager_load(:commenter).collect {...} 

将解决这个问题(上面的代码片段假定您使用的是rails 3)。

+0

我相信eager_load并且包含仅用于活动记录关系的工作。不是数组,在我的文章中,c是一个数组。 – BananaNeil 2011-12-20 02:40:05

+0

它实际上并不是 - 关联就是关系 - 你绝对可以做filtered_ordered_comments = some_blog.comments.where(...)。order(...)例如 – 2011-12-20 08:05:40

2

Collect将为每个评论者加载ActiveRecord对象,每个评论者一次只填写一个字段。包括/ Eager Loading会加载一个查询,这将有助于提高速度,但是如果您希望获得绝对最佳的性能,并且只需要名称,则最好直接与SQL进行比较:

c   = Blog.first.comments 
user_ids = c.collect(&:commenter_id) 
usernames = Commenter.where(['commenter_id IN (?)',user_ids]).select('username').collect(&:username)