2

我有一个包含用户、关系、帖子和喜欢的应用程序。
我的模型是:

class User
  has_many :posts
  has_many :likes
  has_many :relationships, :foreign_key => "follower_id", :dependent => :destroy
end

class Post
  belongs_to :user
  has_many :likes  
end

class Like
  belongs_to :user
  belongs_to :post
end

class Relationship
  belongs_to :follower, :class_name => "User"
  belongs_to :followed, :class_name => "User"
end

所以我想找到至少 100 个喜欢我当前帖子的用户:

friends = User.find(user.followers).likes.where(:post => @post, :limit => 100)

It's a simple but not optimized query if there are a lot of users, posts, likes, etc. in DB.
How can I optimize the query (or models) to increase speed and to decrease query's time execution?

4

3 回答 3

1

嗯,首先要做的是确保所有表都有正确的索引。

因此,用于连接表的所有主键和外键都应该有一个索引。然后,您当然希望在这些表中的任何字段上都有索引,您可能会使用这些索引来进行排序或过滤。

除此之外,我真的没有看到您的数据库架构有任何问题。

但是,如果您想查看非关系数据库,许多开发人员正在使用 NoSQL 存储来解决诸如此类问题,您只有一篇主要帖子,但可能有任意数量的喜欢、评论等。以 JSON 格式维护单个 NoSQL 文档条目真的很容易,其中包含单个帖子的整个树结构,而不是必须从关系数据库结构中的不同表中组装这些信息。

于 2012-09-10T17:01:42.313 回答
0

我同意迈克的观点。您的架构看起来不错,但您应该添加一些索引。

如果您确实遇到了性能问题,您最好的选择是对您的一些数据进行非规范化(即预先计算一些查询并缓存结果)。

一个明显的缓存候选者是存储特定用户或帖子的“喜欢”计数。您可以在每次有人单击“喜欢”时更新它,或者您只能偶尔通过 cron 作业或类似的东西更新计数。然后,您无需实际运行 JOIN 查询即可快速报告“234 人这样的人”。如果您只是有时重新计算它,存储的计数可能会不同步,但这对于这个应用程序来说并不是什么大问题(它不像是银行账户余额!)。

于 2012-09-10T17:10:07.127 回答
0

拥有索引并尝试使用急切加载。就像是

users = User.includes(:likes => [:post]).find(user.followers)
friends = users.where(:post => @post).limit(100)

当您有大量数据时,请使用find_in_batches这将节省内存消耗,因为 Activerecord 内存将在每个批处理事务中释放

于 2012-09-10T17:47:24.283 回答