Rails数据库性能调优

时间:2011-12-19 12:16:06

标签: mysql ruby-on-rails database performance indexing

我目前正在使用非常大的mysql2数据库工作,尽管我已经将我认为正确的字段编入索引,但某些查询的返回时间非常慢。

我有两个导致问题的模型,CommentCommenter

现在,has_manyCommenter之间存在Comment关系,但我的查询依赖于查找每个评论的评论者用户名。所以我会运行这样的事情:

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

为了解决速度问题,我在Comment模型的commenter_id字段上创建了一个索引。但它仍然运行得很慢..

有人知道我能做些什么不同,这有助于提高查询的速度吗?

4 个答案:

答案 0 :(得分:3)

commenter_id上的索引有助于您查找给定commenter_id的评论("找到我做过的所有评论")。

但是当您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)。

答案 1 :(得分: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)

答案 2 :(得分:1)

首先,你在这里做了太多不必要的查询  c.collect {|c| c.commenter.username}  我认为渴望加载可以帮助你。观看此http://railscasts.com/episodes/23-counter-cache-column?autoplay=true

答案 3 :(得分:0)

我想出了使用急切的负载,这不是RaskolnikOFF发布的链接,而是它之前的导轨,http://railscasts.com/episodes/22-eager-loading(仍然给你一个推动我的答案的支持)

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

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

第一行加载第一个博客及其所有关系(并返回博客)。因此,当我调用第二行时,所有内容都已加载并等待访问..

哪种方式比我原来做的更好。