Sql Rails 4:仪表板/分析和查询数据库中的所有记录

Sql Rails 4:仪表板/分析和查询数据库中的所有记录,sql,optimization,ruby-on-rails-4,dashboard,Sql,Optimization,Ruby On Rails 4,Dashboard,在仪表板页面上工作,该页面进行大量分析,以向用户显示图形和表格数据 当仪表板按给定年份进行过滤时,我必须显示所选年份、另一个选择用于比较的年份的分析,以及所有时间的历史平均值 对于所选年份和比较年份,我创建的开始/结束日期时间对象设置为年的开始和年的结束 year = Model.where("closed_at >= ?", start).where("closed_at <= ?", end).all comp = Model.where("closed_at >= ?",

在仪表板页面上工作,该页面进行大量分析,以向用户显示图形和表格数据

当仪表板按给定年份进行过滤时,我必须显示所选年份、另一个选择用于比较的年份的分析,以及所有时间的历史平均值

对于所选年份和比较年份,我创建的开始/结束日期时间对象设置为年的开始和年的结束

year = Model.where("closed_at >= ?", start).where("closed_at <= ?", end).all
comp = Model.where("closed_at >= ?", comp_start).where("closed_at <= ?", comp_end).all
人们以前肯定遇到过这样的问题,并且有一些方法来优化它们吗?回到2000-50000条记录的大致范围内进行历史平均值分析并不是很有效。但是,除非首先检索记录,否则我看不到执行分析的其他方法

选项1:抓取所有内容并使用Ruby进行过滤

由于我已经通过
Model.all
获取了所有信息,因此我可以通过从历史平均值中获取所需的记录来“删除”2年查询。但这似乎是错误的……我实际上是在“下载”我的数据库(可以这么说),然后用Ruby代码而不是SQL查询它。似乎效率很低。以前是否有人尝试过这一点,并看到了任何性能提升

选项2:使用多个SQL DB调用获取选择信息

这意味着我不必在给定的时间段内获取所有记录,而是进行几次数据库查询,从数据库中获取“答案”,而不是在Ruby中分析数据

而不是运行这样的东西

year = Model.where("closed_at >= ?", start).where("closed_at <= ?", end).all
同样,这似乎效率很低,但我对SQL和Ruby代码的效率了解不够,不知道这会导致明显的缺点

我“可以”对这两条路线进行编码,然后相互比较,但是编码/运行它们需要几天的时间,因为仪表板页面上有很多信息我都忽略了。当然,这些情况已经在仪表板/分析页面中多次出现;这类情况是否有一般原则


我正在Rails4上使用PostgreSQL。我也一直在研究特定于DB的解决方案,因为“数据库不可知”对于大多数应用程序来说都是无关紧要的。

Dan,我会研究使用物化视图(MV)来获得历史平均值。这肯定属于“特定于数据库”的解决方案类别,因为MVs在不同的数据库中的实现方式不同(有时甚至完全不同)


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

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

对于我的特定用例,我每天会有几百个用户在任何地方运行这些查询,每次5-20次,因此我实际上没有重大性能问题(即,我不是一个每天为数十亿请求提供服务的Google或Amazon)

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

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

如果遇到性能问题,我的第一步将专门为我查询的数据编制索引,第二步将创建DB视图,“预加载”查询比每次通过实时数据查询更有效

然而,由于DB速度和技术的惊人进步,我不必担心这个问题


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

我实际上是通过不“解决”这个问题来解决这个问题的。我发现我可以直接运行查询,并且运行得很好,没有任何明显的性能问题。在这种情况下,我正在为一个实际上并不需要它的问题进行优化。我可能会发现在未来我需要优化(希望随着用户群的增加!),在这一点上,我认为DB视图可能是一个很好的解决方案。
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...