【发布时间】:2019-07-26 15:33:32
【问题描述】:
我正在为使用 Ruby on Rails 进行的聊天构建一个报告系统,但收到一些 cmets 告诉我我的方法效率低下。
以下是我的报告工作方式的一个小示例:
我有一个处理程序,每个月都会调用一个报告邮件程序,如下所示:
ReportMailer.monthly_report(user).deliver_later
这是邮件的外观:
class ReportMailer < ApplicationMailer
default from: ENV["DEFAULT_MAILER_FROM"],
template_path: 'mailers/report_mailer'
def monthly_report(agent)
@agent = agent
@organization = agent.organization
@report = Report.new @organization
mail(to: agent.email, subject: @report.email_subject)
end
end
我正在尝试使用“普通”Ruby 类计算数据:
module Reports
class Component < Report
def initialize(subject)
@component = subject
@cache = {}
end
attr_reader :component
# DELEGATIONS
# -----------------------
delegate :chat_messages, to: :component
def response_count
count = 0
explore_msgs { |msg, next_msg| count += 1 if response? msg, next_msg }
return count
end
def response_time
time = 0
explore_msgs { |msg, next_msg| time += time_difference msg, next_msg if response? msg, next_msg }
return time.to_i.seconds
end
def avg_response_time
@cache[__method__] ||= (response_time / response_count if response_count > 0)
end
private
def response?(msg, next_msg)
next_msg&.user_type == 'Agent' && msg.user_type == 'User' && msg.conversation_id == next_msg.conversation_id && time_difference(msg, next_msg).seconds < 8.hours
end
def time_difference(msg, next_msg)
(next_msg.created_at - msg.created_at).abs
end
def explore_msgs
chat_messages.each_with_index do |msg, i|
next_msg = chat_messages[i+1]
yield msg, next_msg
end
end
end
end
我关心的是提高性能。我在负责进行计算的类中实现了一个简单的缓存系统,这极大地提高了系统效率,但是,我担心在 Ruby 中进行这些计算可能会产生瓶颈,或者它可能不是一个可扩展的解决方案。
【问题讨论】:
-
在 Web 开发方面有大约 10 年的 XP 经验,我得出的结论是,对于(几乎)任何操作(分组、排序、计数、计算、聚合、搜索),数据库(几乎)总是更好, ETC)。您可能希望将计算保存在
SQL视图(或物化视图)中,或者将其保存在您的 Rails 代码中。 -
这里要注意一点。由于您正在做的事情,您冒着构建相关查询的风险,这可能是一个缓慢的数据库操作。因此,如果您想获得比 ruby 更快的数据库处理速度,请务必避免相关查询。
-
正如@MrYoshiji 所说,在数据库中做尽可能多的事情,而不是检索原始数据并使用Ruby 来处理它。 DBM 包含针对与 DB 相关的事情的非常优化的代码,所以让它去做,因为它更接近数据。移动数据会影响 Rails 机器上的网络、驱动器和 CPU,这些机器确实需要专注于运行 Rails 和处理请求。此外,听起来您正在将 Rails 与 Ruby 区分开来。 Rails 是 Ruby 代码,Ruby 处理它,所以除非你重写 Rails 代码做得更好的轮子,否则没有区别。
标签: mysql ruby-on-rails performance greatest-n-per-group