【问题标题】:Optimize a query using active record rails使用活动记录轨道优化查询
【发布时间】:2016-12-25 21:05:04
【问题描述】:

rails 模型中的数据库关系:

Class User < ActiveRecord::Base
  has_many :user_messages
  has_many :messages
end

Class UserMessage < ActiveRecord::Base
  belongs_to :user
  belongs_to :message
end

Class Message < ActiveRecord::Base
  belongs_to :user
  has_many :user_messages
end

我要优化以下代码:

ids.each do |id|
  user = User.find_by_id(id)
  unread_count = user.user_messages.where(:folder => user.inbox_id, :read => false).count
  puts "UserID #{id} ---- Unread Message count #{unread_count}"
end

能否告诉我如何使用 Active Record 或 SQL Query 优化上述代码。我基本上是想减少数据库查询和上述代码完成循环所需的时间。

提前致谢。

【问题讨论】:

  • 听起来像是一个左连接的工作,与一个 group by 和 count。您是否尝试过为 sql 做一个基础教程?
  • 您应该在users 表中存储一个unread_count 列,以便为每个用户存储unread_count
  • 我可以将 unread_count 存储在 users 表中,因为我使用此 Model.import 方法在 user_messages 表中插入了批量数据。

标签: mysql sql ruby-on-rails postgresql


【解决方案1】:

你可以这样做:

users = User.where(id: ids).includes(:user_messages)
users.each do |user|
  unread_count = user.user_messages.where(:folder => user.inbox_id, :read => false).count
  puts "UserID #{user.id} ---- Unread Message count #{unread_count}"
end

由于您急切地加载user_messages,它不会触发循环内的任何其他数据库查询。只有 1 个查询来获取用户,它是 user_messages。

或者你可以这样做:

user_messages = UserMessage.joins(:user).where('folder = users.inbox_id AND read = false').group(:user_id).count
# user_messages = {1=>10, 2=>19}
# Here keys are user ids and values are no of user_messages for that user

user_messages.each do |user_id,unread_msg_count|
  puts "UserID #{user_id} ---- Unread Message count #{unread_msg_count}"
end

PS:我没有测试任何代码,如果有任何错误请评论。我在这里假设puts "UserID #{ids} 你想放置一个用户 ID 并根据它修改我的代码,因为在你的代码中它将打印所有 ID ids

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    相关资源
    最近更新 更多