【发布时间】:2014-03-14 04:10:08
【问题描述】:
在仪表板页面上工作,该页面执行大量分析以向用户显示图形和表格数据。
当仪表板按给定年份过滤时,我必须显示所选年份的分析、选择用于比较的另一年份以及所有时间的历史平均值。
对于选定年份和比较年份,我创建了设置为 begin_of_year 和 end_of_year 的开始/结束 DateTime 对象。
year = Model.where("closed_at >= ?", start).where("closed_at <= ?", end).all
comp = Model.where("closed_at >= ?", comp_start).where("closed_at <= ?", comp_end).all
这些查询本质上是相同的,只是日期过滤器不同。除了尝试仅“选择(...)”我需要的字段之外,我真的没有看到任何优化方法,这可能是所有字段。
由于在某一年平均会有 250-1000 条记录,因此它们并不“可怕”(在我不太熟练的意见中)。
但是,历史平均值让我很痛苦。为了充分显示平均值,我必须查询所有时间的所有记录并对其执行计算。这是一个坏主意,但我不知道如何解决。
all_for_average = Model.all
肯定人们以前遇到过这类问题并且有一些优化它们的方法吗?返回 2,000 - 50,000 条记录以进行历史平均分析并不是很有效。但是,除非我首先检索记录,否则我看不到执行分析的其他方法。
选项 1:抓取所有内容并使用 Ruby 进行过滤
由于我已经通过Model.all 获取所有内容,因此我“可以”通过简单地从历史平均值中获取所需记录来删除 2 年查询。但这似乎是错误的……我实际上是在“下载”我的数据库(可以这么说),然后用 Ruby 代码而不是 SQL 来查询它。看起来效率很低。有没有人尝试过这个并看到任何性能提升?
选项 2:使用多个 SQL DB 调用来获取选择信息
这意味着我不会获取给定时间段内的所有记录,而是进行多个数据库查询以从数据库中获取“答案”,而不是在 Ruby 中分析数据。
而不是像这样运行,
year = Model.where("closed_at >= ?", start).where("closed_at <= ?", end).all
我会执行多个查询:
year_total_count = Model.where(DATE RANGE).size
year_amount_sum = Model.where(DATE RANGE).sum("amount")
year_count_per_month = Model.where(DATE RANGE).group("MONTH(closed_at)")
...other queries to extract selected info...
同样,这似乎非常低效,但我对 SQL 和 Ruby 代码效率的了解不足,无法知道哪些会导致明显的缺点。
我“可以”对两条路线进行编码,然后将它们相互比较,但编码/运行它们需要几天时间,因为我忽略了仪表板页面上的大量信息。当然,对于仪表板/分析页面,这些情况已经多次出现;对这些类型的情况有一般原则吗?
我正在使用 PostgreSQL on Rails 4。我也一直在研究特定于数据库的解决方案,因为“与数据库无关”对于大多数应用程序来说确实无关紧要。
【问题讨论】:
标签: sql optimization ruby-on-rails-4 dashboard