我正在应用程序中构建多个报告,并且遇到了构建报告的几种方法,并且希望能够采用最佳/常用方法来构建可扩展且尽可能实时的报告.
首先,一些条件/限制/目标:
Project,并且项目持续了6个月,有一堆活动,但现在已经结束了),报告应该永久保存,以便随后的检索只需要预先计算的文件.报告不需要是可搜索的,因此一旦数据在文档中,我们只是显示文档.客户端基本上获得了一个代表所有统计数据,图表等的JSON树,因此它可以在Javascript中呈现.
我的问题出现了,因为我试图找到一种方法来对大型数据集进行实时报告.
假设我正在报告网站上的整体用户注册和活动.该网站拥有100万用户,平均每秒有1000次页面浏览量.有一个User模型和PageView模型可以说,在哪里User has_many :page_views.说我有这些统计数据:
report = {
:users => {
:counts => {
:all => user_count,
:active => active_user_count,
:inactive => inactive_user_count
},
:averages => {
:daily => average_user_registrations_per_day,
:weekly => average_user_registrations_per_week,
:monthly => average_user_registrations_per_month,
}
},
:page_views => {
:counts => {
:all => user_page_view_count,
:active => active_user_page_view_count,
:inactive => inactive_user_page_view_count
},
:averages => {
:daily => average_user_page_view_registrations_per_day,
:weekly => average_user_page_view_registrations_per_week,
:monthly => average_user_page_view_registrations_per_month,
}
},
}
Run Code Online (Sandbox Code Playgroud)
我尝试过的事情:
User和PageView都是ActiveRecord对象,所以一切都是通过SQL.我抓住了这样的块中的所有用户:
class User < ActiveRecord::Base
class << self
def report
result = {}
User.find_in_batches(:include => :page_views) do |users|
# some calculations
# result[:users]...
users.each do |user|
# result[:users][:counts][:active]...
# some more calculations
end
end
result
end
end
end
Run Code Online (Sandbox Code Playgroud)
MongoMapper::Document对象Map-reduce在现场计算真的很慢,我还没有花时间弄清楚如何使这项工作实时化(检查出蜂鸟).基本上我做同样的事情:将记录分块,将结果添加到哈希,就是这样.
这是Rails 统计宝石所采用的方法.我唯一不喜欢的是这可能会产生的查询量(没有基准测试是否每个请求每个报告执行30个查询比将所有对象分块到内存中并且直接在红宝石中排序更好)
我想的问题是,从您的经验来看,对大型数据集进行实时报告的最佳方式是什么?通过对内存中的记录进行分块/排序每个请求(我现在正在做什么,我可以使用每小时cron进行一些优化,但这不是实时),报告需要大约一秒钟来生成(复杂的日期公式和这样),有时更长.
除了传统的优化(更好的日期实现,sql/nosql最佳实践),我可以在哪里找到一些关于构建报告的实用且经过验证的文章?我可以建立报告没问题,问题是,你如何快速,实时,优化和正确?真的没找到任何东西.
为您的用例构建近实时报告的最简单方法是使用缓存。
所以在report方法中,需要使用rails缓存
class User < ActiveRecord::Base
class << self
def report
Rails.cache.fetch('users_report', expires_in: 10.seconds) do
result = {}
User.find_in_batches(:include => :page_views) do |users|
# some calculations
# result[:users]...
users.each do |user|
# result[:users][:counts][:active]...
# some more calculations
end
end
result
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
在客户端,您只需使用 ajax 池请求此报告。这样,生成此报告就不会成为瓶颈,因为生成报告大约需要 1 秒,并且许多客户可以轻松获得最新结果。
为了获得更好的用户体验,您可以存储两个报告之间的增量,并使用此增量预测在客户端增加您的报告,如下所示:
let nextPredictedReport = null;
let currentReport = null;
const startDrawingPredicted = () => {
const step = 500;
const timePassed = 0;
setInterval(() => {
timePassed += step;
const predictedReport = calcDeletaReport(currentReport, nextPredictedReport, timePassed);
drawReport(predictedReport);
}, step);
};
setInterval(() => {
doReportAjaxRequest().then((response) => {
drawReport(response.report);
currentReport = response.report;
nextPredictedReport = response.next_report;
startDrawingPredicted();
});
}, 10000);
Run Code Online (Sandbox Code Playgroud)
这只是该方法的一个示例,calcDeletaReport应该drawReport由您自己实现+此解决方案可能有问题,因为它只是一个想法:)
| 归档时间: |
|
| 查看次数: |
1236 次 |
| 最近记录: |