【问题标题】:Rails 4: dashboard/analytics and querying ALL records in DBRails 4:仪表板/分析和查询数据库中的所有记录
【发布时间】: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


    【解决方案1】:

    Dan,我会考虑使用物化视图 (MV) 来获取历史平均值。这肯定属于“特定于数据库”的解决方案类别,因为 MV 在不同数据库中的实现方式不同(或者有时根本没有)。 Here is the basic PG documentation.

    物化视图本质上是一个物理表,只是它的数据是基于对其他表的查询。在这种情况下,您可以创建一个基于平均历史数据的查询的 MV。如果基础数据未更改,则此查询仅运行一次。然后仪表板可以只对这个 MV 执行一个简单的读取查询,而不是在基础表上运行代价高昂的查询。

    【讨论】:

    • 我实际上解决了这个问题,实际上并没有“解决”它。我发现我可以只运行查询,它运行良好,没有任何明显的性能影响。在这种情况下,我正在针对实际上并不需要它的问题进行优化。将来我可能会发现我需要优化(希望随着用户群的增加!),那时我认为数据库视图可能是一个很好的解决方案。
    【解决方案2】:

    在与其他更有经验的 DBA 和开发人员讨论该问题后,我决定尝试优化一个尚不需要任何优化的问题。

    对于我的特定用例,我每天会有数百名用户运行这些查询,每次运行 5 到 20 次不等,因此我并没有真正遇到重大的性能问题(即,我不是 Google 或 Amazon每天处理数十亿个请求)。

    我实际上只是让 PostgreSQL 数据库每次都执行查询,我没有注意到我的用户有任何重大的性能问题;页面加载速度非常快,查询/图表没有明显延迟。

    对于尝试解决类似问题的其他人,我建议尝试在暂存环境中运行一段时间,看看您是否真的有需要首先解决的问题。

    如果我遇到性能问题,我的第一步是专门为我查询的数据建立索引,我的第二步是创建数据库视图,与每次通过实时数据查询它们相比,它可以更有效地“预加载”查询。

    不过,由于数据库速度和技术的惊人进步,我不必担心这个问题。

    我正在回答我自己的问题,以便其他人可以花时间解决更有利可图的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-08
      • 2020-10-30
      • 2020-05-03
      • 1970-01-01
      • 2019-05-19
      • 2011-03-04
      • 1970-01-01
      相关资源
      最近更新 更多