如何实现快速多指标计算
在统计分析应用中,从明细数据计算出来的各种指标是支撑业务的重要数据。但是,要做到快速而且灵活的多指标计算,后台数据源面临多个难题。
多指标计算的一个难题是涉及的明细数据量非常大。政府、金融、能源和工业等各个行业,都在不断产生大量的明细数据。要在几千万甚至上亿的明细数据基础上计算多种指标,还要达到秒级响应的速度,对于传统数据库和大数据技术来说都是一个不小的挑战。
另一个难题是需要同时计算的指标数量非常多。我们常常看到,一个管理页面上就要显示出几十上百个指标供业务人员参考,页面上还有很多可选参数用于计算不同的指标值。而且,业务人员的数量通常也比较多,在高峰时段同时访问指标页面时,会给后台带来大量的计算请求。
在这两个难题的共同作用下,要保证多指标计算的性能非常困难,现有的数据库和大数据技术都难以达到秒级响应速度。所以,大部分指标统计项目都放弃了指标的实时计算方案,采用预先计算的方法,提前将指标计算出来存储在后台,供业务人员查询。这样,指标的计算就变成简单的随机查找,可以达到秒级响应的速度。
但是,预先计算方式也面临一个严重的问题。指标计算过程中,过滤条件有很多种、分组字段有很多类,汇总计算有很多方式。这些种类、方式组合起来形成的指标数量非常惊人。以常见的订单金额和笔数指标为例,过滤条件有时间日期、交易金额、渠道等,分组类型有客户、地区、产品等,统计方式有求和、求平均、最大、最小、topN 等。组合出来的指标如:昨日北美地区 10000-20000 元消费额订单,按照客户和产品分组,汇总平均金额和订单总笔数。这个指标只要稍加改变,就会组合出另外一个新指标。因此,全部指标的总数非常大,要预先计算出来的结果太多,指标计算后台根本无法全部存下。
面对这个问题,多数项目都只能舍弃大部分指标,仅预计算一小部分指标供查询,即使这样也会占用大量的硬盘存储空间。而业务人员只能放弃对更多指标的灵活查询需求,会大大降低指标统计项目对业务的支撑作用。
那么有没有办法既能做到灵活的实时计算,又可以达到秒级响应的速度呢?我们可以从多指标计算的特征入手来达到这个目标。明细数据量很大,通常都是外存存储。多指标计算最主要的过程是对外存大明细表进行遍历,以完成过滤、分组和汇总计算。我们知道,对硬盘上的大文件进行遍历耗时比较长。假如每个指标的计算都要遍历一次大明细表,那么硬盘 IO 就会成为瓶颈,众多指标的计算就不可能做到秒级响应了。如果有办法能够做到一次遍历计算多个指标,就可以大大减少遍历次数,有效提升多指标计算的性能。
但是,关系数据库和大数据平台普遍采用的 SQL 语言没有这种遍历复用的语法,无法写出这样的运算。只能遍历多次,或者寄希望于数据库引擎的自动优化功能。但是实际测试证明,即使是优化引擎做的较好的 Oracle 数据库,也不会自动做遍历复用计算,进行多种分组时还是会对数据表遍历多次。
专业的数据计算引擎 esProc SPL支持这种遍历复用的语法,可以一次遍历计算出多个分组结果,从而实现实时的指标计算。以上面提到的订单指标为例,下面的代码可以一次遍历计算出多种指标:
A |
B |
|
1 |
=file("orders.ctx").open() |
|
2 |
=A1.cursor@m(odate,customer,product,area,amount) |
|
3 |
cursor A2 |
=A3.select(odate==… && area=="NorthAmerica" &&…) |
4 |
=B3.groups(customer;sum(amount),count(1)…) |
|
5 |
cursor |
=A5.select(odate>=… && customer!=… &&…) |
6 |
=B5.groups(area;avg(amount),top(amount,100),…) |
|
7 |
cursor |
=A7.groups(year(odate),product;avg(amount),min(amount)…) |
8 |
… |
… |
A1 打开订单组表。A2 建立多路游标,声明要并行取出的字段名称。
A3 对 A2 游标定义一个管道。B3 对管道定义过滤计算,B4 对过滤的结果进行分组汇总计算,得出第一组指标。
A5 到 B6 也对 A2 游标定义了一个管道,只是过滤条件和分组汇总的方式不同,可以得到第二组指标。
对于 B6 中订单金额前一百名的计算,SPL 也看做是聚合运算,与 SQL 中的大排序方法相比有很大的性能优势。详情参见:TopN 怎样才能跑得快?
A7、B7 对 A2 游标定义了第三个管道,不经过过滤直接分组汇总得到第三组指标。
SPL 执行代码时对 A2 游标做一次遍历,就可以完成全部管道的计算,得到多组指标,从而实现了遍历复用机制。
这个例子是对于单表的遍历复用,SPL 也支持高性能的表间关联计算,参见:如何让 JOIN 跑的更快。
对于需要作去重计算的指标,比如去重客户数等,SPL 提供有序存储、快速去重的技术,参见:SQL 提速:大数据 DISTINCT 和 COUNT(DISTINCT)。
在 SPL 中,可以用很简捷的代码实现这些高性能计算方法,并且和遍历复用协同使用,整体上的性能完全能够满足指标实时计算的要求。