如何實現(xiàn)海量數(shù)據(jù)下有序漏斗秒查

近期易觀公司舉辦了一個OLAP大賽,我們隊伍非常幸運地獲得了第一名,成為本次比賽最大黑馬。此篇文章主要是從技術(shù)角度飒房,來分享一下我們是如何解決有序漏斗秒查問題的

比賽地址:2017易觀OLAP算法大賽

參賽情況:? https://www.analysys.cn/media/detail/20018458/

1.? 題目分析:

在以上示例場景下,我們在易觀提供的6億測試數(shù)據(jù)集上媚值,在4臺UCloud云主機(16core狠毯,16G ram)機器下從24s優(yōu)化到了0.5s。而在正式比賽的26億數(shù)據(jù)集上褥芒,使用相同硬件環(huán)境嚼松,耗時1.6s。

2.? 解題分析:

題目描述的有序漏斗問題可以歸結(jié)為 帶滑動時間窗口的最左子序列問題锰扶, 比如我們需要尋找献酗,2017年7月份中,在3小時的時間窗口下坷牛, [A,B,C,D] 漏斗路徑下的轉(zhuǎn)化情況罕偎, 單個用戶只能有? NULL , [a], [A,B], [A,B,C], [A,B,C,D]? 五種轉(zhuǎn)化結(jié)果,對應(yīng)的漏斗深度我們稱之為level京闰,在[A,B,C,D]漏斗路徑下颜及,level的取值可以有[0,1,2,3,4] 四個值,題目的要求即算出所有用戶的滿足條件下最大level匯總結(jié)果蹂楣。

理解問題之后俏站,我們梳理了一下流程圖:

我們將問題解決分為5個步驟:

filter階段 :根據(jù)時間區(qū)間和事件屬性對數(shù)據(jù)進行過濾

group階段: 根據(jù)用戶Id進行g(shù)roup匯總

sort階段: 按照時間進行排序

algorithm aggregate 階段: 帶時間窗口的子序列搜索

合并結(jié)果

3.? 數(shù)據(jù)庫選型:

根據(jù)以上分析,需要filter捐迫,group乾翔,sort爱葵,aggregate等操作施戴,數(shù)據(jù)庫是必備的核心反浓,而在OLAP領(lǐng)域,開源的數(shù)據(jù)庫選型有很多赞哗,比如:mysql, druid, kylin hdfs + (hive,spark,presto)雷则,imapla, kudu etc。

但在這個場景下肪笋,結(jié)合以往對其他數(shù)據(jù)的深入研究分析對比經(jīng)驗月劈,我們幾乎毫不猶豫就選擇了 ClickHouse (縱然它不支持udaf),藤乙,我們相信ClickHouse是目前cpu領(lǐng)域最快的olap開源數(shù)據(jù)庫猜揪,它最突出的優(yōu)點就是快,如果你是第一次用坛梁,相信ClickHouse會讓你感到非常驚艷而姐。

ClickHouse 由俄羅斯Yandex開發(fā),09年原型划咐,12年生產(chǎn)可用拴念,16年開源,目前最大的線上部署實例是 Yandex.Metrica: 472個節(jié)點褐缠,每秒處理2T數(shù)據(jù)政鼠,實時在線分析。ClickHouse 在OLAP上的查詢性能非常彪悍队魏,平均查詢性能幾乎是vertica的三倍公般。

ClickHouse不僅速度快,它系統(tǒng)架構(gòu)靈活胡桨,性能優(yōu)越俐载,代碼優(yōu)雅, 非常適合大數(shù)據(jù)下需要極致性能的應(yīng)用場景。雖然ClickHouse目前暫不支持UDAF登失,但沒關(guān)系遏佣,由于它的架構(gòu)非常好,我們可以通過修改源代碼并重新編譯來實現(xiàn)自定義AggregateFunction (即使我還是一個 c++ 菜鳥 ~~ )揽浙。

以上就是針對漏斗場景的代碼修改情況状婶,可以看出我們只用了不到300行代碼就為ClickHouse加入了漏斗計算(aggregate function path)的功能, 修改的代碼可以在文章末尾看到。

對比官方的presto + hdfs 方案實現(xiàn)的24s速度馅巷,使用ClickHouse之后膛虫,我們在測試環(huán)境下跑的速度達到了8s,這僅僅是一個基礎(chǔ)版本的性能钓猬。

下面開始我們的正式優(yōu)化過程

4. 按照用戶ID分區(qū):

我們注意到稍刀,漏斗的計算中,每個用戶都是相互獨立的,所以我們可以將數(shù)據(jù)按照uid來分區(qū)账月,這樣就將數(shù)據(jù)分散到了四臺機器上综膀,我們可以分別向每個數(shù)據(jù)庫節(jié)點發(fā)送請求,然后將數(shù)據(jù)進行匯總局齿,得到最終結(jié)果剧劝。

通過這次優(yōu)化,我們在測試環(huán)境下跑的速度達到了1.6s抓歼。

5. 以(uid,timestamp)作為primary key

ClickHouse中primary key代表了數(shù)據(jù)的組織排序方式

左邊的以(timestamp讥此,uid)為主鍵,時間是有序的谣妻,方便做時間精準(zhǔn)過濾萄喳,但uid壓縮率低;右邊的以(uid,timestamp) 為主鍵蹋半,uid壓縮率高取胎,方便做uid group, 但對時間過濾支持不夠好湃窍。

通過測試對比闻蛀,我們發(fā)現(xiàn)以 (uid,timestamp) 作為主鍵性能略快,查詢時間達到了 1.4s您市。

6. 分組預(yù)排序

當(dāng)我們以 (uid,timestamp) 作為primary key后觉痛, 分組內(nèi)的數(shù)據(jù)其實已經(jīng)有序了, 我們可以去掉代碼中的sort方法茵休,來提高性能薪棒,經(jīng)過這個優(yōu)化,查詢時間達到了 0.9s榕莺。

7. 帶時間窗口的子序列搜索優(yōu)化

這里主要是用了一些 剪枝的策略俐芯,當(dāng)我們從左往右去搜索 a,b,c,d 漏斗的時候,我們需要找到最大的深度钉鸯,必須一直去搜索以a開頭的子序列吧史;但我們從右往左搜索時, 我們只要考慮比當(dāng)前結(jié)尾更大的子串即可唠雕, 比如我們找到了 a,b,c贸营, 后面我們只需要考慮以d結(jié)尾的串,這樣減小了搜索的復(fù)雜度岩睁,查詢時間達到了0.8s钞脂。

8. 數(shù)據(jù)結(jié)構(gòu)優(yōu)化

事件ID到數(shù)組下標(biāo)Index的映射,我們直接遍歷了數(shù)組搜索捕儒,而不使用std::unordered_map, 因為在events數(shù)據(jù)量不大的情況下冰啃, 數(shù)組搜索O(1)比O(n)慢。

使用純C++數(shù)組存儲事件序列,不使用std::vector阎毅,去掉了vector的開銷焚刚,靈活控制內(nèi)存分配。

經(jīng)此優(yōu)化净薛,查詢時間達到了0.6s。

9. 部分壓縮

數(shù)據(jù)庫通常會對字段進行壓縮蒲拉,這樣做節(jié)省了硬盤空間肃拜,但卻浪費了cpu計算,為了提供性能雌团,我們對字段進行了部分壓縮燃领,經(jīng)此優(yōu)化,查詢時間達到了最終的0.5s锦援。

uid? => 壓縮

timestamp => 不壓縮

event_id => 不壓縮

event_name => 壓縮

event_tag => 壓縮

date => 不壓縮

最后:

我們已經(jīng)將代碼和PPT開源:https://github.com/analysys/olap

為了滿足通用漏斗的查詢猛蔽,結(jié)合電商分析的場景,新版的 windowFunnel 函數(shù)已提交給ClickHouse 官方灵寺,已被官方采納? Add AggregateFunction windowFunnel? by sundy-li · Pull Request #2352 · yandex/ClickHouse通過這次比賽曼库,0.5s的性能非常突出,但這絕不會是極限略板,如今GPU數(shù)據(jù)庫大道橫行毁枯,技術(shù)變革也愈演愈烈, 前路漫長叮称,預(yù)測未來最好的方法就是自己創(chuàng)造未來种玛,各位技術(shù)大牛們,一起努力H块堋B冈稀!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末挠蛉,一起剝皮案震驚了整個濱河市祭示,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谴古,老刑警劉巖绍移,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異讥电,居然都是意外死亡蹂窖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門恩敌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞬测,“玉大人,你說我怎么就攤上這事≡绿耍” “怎么了灯蝴?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長孝宗。 經(jīng)常有香客問我穷躁,道長,這世上最難降的妖魔是什么因妇? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任问潭,我火速辦了婚禮,結(jié)果婚禮上婚被,老公的妹妹穿的比我還像新娘狡忙。我一直安慰自己,他們只是感情好址芯,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布灾茁。 她就那樣靜靜地躺著,像睡著了一般谷炸。 火紅的嫁衣襯著肌膚如雪北专。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天旬陡,我揣著相機與錄音逗余,去河邊找鬼。 笑死季惩,一個胖子當(dāng)著我的面吹牛录粱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播画拾,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼啥繁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了青抛?” 一聲冷哼從身側(cè)響起旗闽,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜜另,沒想到半個月后适室,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡举瑰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年捣辆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片此迅。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡汽畴,死狀恐怖旧巾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情忍些,我是刑警寧澤鲁猩,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站罢坝,受9級特大地震影響廓握,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嘁酿,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一隙券、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧痹仙,春花似錦是尔、人聲如沸殉了。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽薪铜。三九已至众弓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隔箍,已是汗流浹背谓娃。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蜒滩,地道東北人滨达。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像俯艰,于是被迫代替她去往敵國和親捡遍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容