近期易观公司举办了一个OLAP大赛,咱们队伍很是荣幸地得到了第一名,成为本次比赛最大黑马。此篇文章主要分享一下咱们是如何解决有序漏斗秒查问题的html
比赛地址:2017易观OLAP算法大赛mysql
参赛状况: https://www.analysys.cn/media/detail/20018458/git
在以上示例场景下,咱们在易观提供的6亿测试数据集上,在4台UCloud云主机(16core,16G ram)机器下从24s优化到了0.5s。而在正式比赛的26亿数据集上,使用相同硬件环境,耗时1.6s。github
题目描述的有序漏斗问题能够归结为 带滑动时间窗口的最左子序列问题, 好比咱们须要寻找,2017年7月份中,在3小时的时间窗口下, [A,B,C,D] 漏斗路径下的转化状况, 单个用户只能有 NULL , [a], [A,B], [A,B,C], [A,B,C,D] 五种转化结果,对应的漏斗深度咱们称之为level,在[A,B,C,D]漏斗路径下,level的取值能够有[0,1,2,3,4] 四个值,题目的要求即算出全部用户的知足条件下最大level汇总结果。算法
理解问题以后,咱们梳理了一下流程图:sql
咱们将问题解决分为5个步骤:数据库
根据以上分析,须要filter,group,sort,aggregate等操做,数据库是必备的核心,而在OLAP领域,开源的数据库选型有不少,好比:mysql, druid, kylin hdfs + (hive,spark,presto),imapla, kudu etc。数组
但在这个场景下,结合以往对其余数据的深刻研究分析对比经验,咱们几乎坚决果断就选择了 ClickHouse (纵然它不支持udaf),,咱们相信ClickHouse是目前cpu领域最快的olap开源数据库,它最突出的优势就是快,若是你是第一次用,相信ClickHouse会让你感到很是惊艳。数据结构
ClickHouse 由俄罗斯Yandex开发,09年原型,12年生产可用,16年开源,目前最大的线上部署实例是 Yandex.Metrica: 472个节点,每秒处理2T数据,实时在线分析。ClickHouse 在OLAP上的查询性能很是彪悍,平均查询性能几乎是vertica的三倍。架构
ClickHouse不只速度快,它系统架构灵活,性能优越,代码优雅, 很是适合大数据下须要极致性能的应用场景。ClickHouse目前暂不支持UDAF,但不要紧,咱们能够经过修改源代码并从新编译来实现自定义AggregateFunction。
以上就是针对漏斗场景的代码修改状况,能够看出咱们只用了不到300行代码就为ClickHouse加入了漏斗计算(aggregate function path)的功能。
对比官方的presto + hdfs 方案实现的24s速度,使用ClickHouse以后,咱们在测试环境下跑的速度达到了8s。
下面开始咱们的正式优化过程
咱们注意到,漏斗的计算中,每一个用户都是相互独立的,因此咱们能够将数据按照uid来分区,这样就将数据分散到了四台机器上,咱们能够分别向每一个数据库节点发送请求,而后将数据进行汇总,获得最终结果。
经过此次优化,咱们在测试环境下跑的速度达到了1.6s。
ClickHouse中primary key表明了数据的组织排序方式
左边的以(timestamp,uid)为主键,时间是有序的,方便作时间精准过滤,但uid压缩率低;右边的以(uid,timestamp) 为主键,uid压缩率高,方便作uid group, 但对时间过滤支持不够好。
经过测试对比,咱们发现以 (uid,timestamp) 做为主键性能略快,查询时间达到了 1.4s。
当咱们以 (uid,timestamp) 做为primary key后, 分组内的数据其实已经有序了, 咱们能够去掉代码中的sort方法,来提升性能,通过这个优化,查询时间达到了 0.9s。
这里主要是用了一些 剪枝的策略,当咱们从左往右去搜索 a,b,c,d 漏斗的时候,咱们须要找到最大的深度,必须一直去搜索以a开头的子序列;但咱们从右往左搜索时, 咱们只要考虑比当前结尾更大的子串便可, 好比咱们找到了 a,b,c, 后面咱们只须要考虑以d结尾的串,这样减少了搜索的复杂度,查询时间达到了0.8s。
事件ID到数组下标Index的映射,咱们直接遍历了数组搜索,而不使用std::unordered_map, 由于在events数据量不大的状况下, 数组搜索O(1)比O(n)慢。
使用纯C++数组存储事件序列,不使用std::vector,去掉了vector的开销,灵活控制内存分配。
经此优化,查询时间达到了0.6s。
数据库一般会对字段进行压缩,这样作节省了硬盘空间,但却浪费了cpu计算,为了提供性能,咱们对字段进行了部分压缩,经此优化,查询时间达到了最终的0.5s。
总结:
咱们已经将代码和PPT开源:
https://github.com/analysys/olap
0.5s固然不会是极限,现在GPU数据库大道横行,技术变革也愈演愈烈, 前路漫长,预测将来最好的方法就是本身创造将来。
[1] 如何实现海量数据下有序漏斗秒查
https://zhuanlan.zhihu.com/p/30823204
[2] analysys/olap
https://github.com/analysys/olap
[3] 易观olap大赛
http://ds.analysys.cn/OLAP.html
[4] 易观OLAP算法大赛结果揭晓,开源组黑马放大招!