【均一】資料架構與分析

Young Tsai
Young
Published in
12 min readJan 22, 2019

前言

我們希望能夠使用老師、學生在均一平台產生的資料,幫助功能開發的決策。無奈剛開始做資料分析的時候,沒有完整的資料分析架構去幫助資料分析。經過了兩年多的思考和嘗試,現在均一的資料收集和處理系統有一個相較以往完整的雛形,在此篇文章將分享以及回顧這段過程,希望可以幫助到需要自己建立資料處理系統的讀者。

本文分(上)、(下) 兩篇,(上)篇會著重在各種資料的收集,儲存進統一的資料庫,(下)篇則會著重在這些資料後續的處理和應用。

PS: 此篇文章非作者原創,為均一前資料科學家 En 與 筆者 Young 共同創作

均一資料架構與應用(上)

早期的均一資料架構

目前的資料架構

最初作法:先用既有的 DB 分析看看

均一平台一開始只有網站儲存的 DB 而已,所以先藉著把在 Google Cloud Storage 備份的 DB 資料匯入 BigQuery 的方式,先把網站(Google App Engine)內部的資料備份到 Google Cloud Storage,之後再匯入 BigQuery(線(1))。接著用 BigQuery 內建的語法,來做 Query 和資料分析。當然… 單純用 BigQuery 的 console 來操作資料也太辛苦了,分析結果也很難保存,因此很快就開始用 R studio, Pandas + Ipython 介接 BigQuery 的方式來做資料分析(線(6))。

挑戰一:DB 資料不適合/不夠做資料分析

因為一開始存在網站的 DB 目的是為了網站的運作,不是為了使用者行為的分析,因此很多資料分析不到亦或是難以從 DB 重現。
因此我們藉由 Google App Engine 內建的 Streaming Logging 的方式,把資料 Logging 到 BigQuery (Logging Data),這樣做相比於匯入 Google App Engine 內建 DB 到 BigQuery (路線 1)有以下優點,因此,至今我們大部分的資料分析都是使用路線(2) 的方式匯入的資料,只有少數資料表仍然仰賴網站 DB 的匯入。

Logging Data 的好處:

1. 更具有彈性(不需要建立對應的 DB)

2. 更即時(DB 的匯入是 Jenkins 工作排程,非即時)

3. 在運算、儲存資源的運用上也更有效率 (DB 一次一定是整個匯入,如果是跟時間 Logging 有關的 DB,其實每週匯入重複的資料量很大。)

挑戰二:不容易收集到 Client 端行為

隨著分析的需求和作法越來越多樣,我們希望能更直接看到均一網站 Client 端的使用者行為(ex. 使用者按了哪些按鈕、從哪一頁逛到哪一頁云云),所以還想把使用者在前端的行為也 Logging 到 BigQuery,這單純用路線(2) 是做不到的。

我們最後決定研究看看有沒有機會直接把 Google Analytics (GA) 裡面的資料自動匯出來,會這樣想的原因是因為

1. 可以儘量減少在系統中的實作

2. 均一網站內部已經埋了很多 GA page view 和 GA event,這樣就不用重新埋了

3. GA 另外還有幫忙記錄了很多資料,包含使用者的裝置型號、使用者位置等資料,希望也可以整合進自己的 BigQuery 使用

解法:
基於上面三個原因,我們研究了 GA 的各種 API,結果真的有一種方式,可以達成我們的需求:把網站 Logging 到 Google Analytics 的所有資料匯出來(目前是在 Jenkins 上每天跑一次),再存到 BigQuery (或是其他的資料庫)。其實 GA API 本身沒有想要支援這樣的功能(倒出原始資料),它的 API 只想要給你資料統計之後的結果,但是因為它同時有 Custom Dimension,所以只要確認你設定的 Custom Dimension 可以造成每比資料都是獨一無二的,那麼統計的結果也就會跟這一比資料的內容一致了(GA 每天提供足夠多的 Request 次數讓我們把所有的原始資料匯出)。我們有在 GitHub Open Source 詳細的作法,叫做 dauGA (倒 GA) ,希望可以給大家一點幫助。

挑戰三:加入 AB test ,進行 Randomize Control 的實驗

截至目前為止的作法,並不包含 AB test 的功能,我們當初承襲可汗學院,使用 Open Source 套件 gae_bingo 來做 AB test ,無奈 gae_bingo 自成一套體系,無法跟我們其他儲存的資料做對照,另外 gae_bingo 很吃記憶體、以及因為實作上牽涉到 Google App Engine 的底層,容易產生一些難解的 Bug 。經過討論以後,我們決定把 gae_bingo 從均一當中拔掉,並參考它的設計,實作了一個很簡單的 AB test 工具,並且和現有的 Logging 機制(路線(2)) 做整合。

實作方法:
我們利用使用者的 unique id ,加上一些 random 參數,一起 hash 成數字後,取 mod 的方式來做使用者分群,(ex. 如果 A 組:B 組 = 9 : 1 的話,就把所有使用者 hash 過後的結果取 mod 10,餘數是 0 的取 B 組,其他 A 組)。我們把分組的結果也透過路線(2)的方式也存在 BigQuery,基本上只存三個欄位:unique id, 什麼實驗, 以及哪一組。要參照實驗的結果,就把不同的實驗組別,藉由使用者的 unique id 和其他 BigQuery 的資料表做 JOIN,然後再做各種統計上的分析。

這樣的作法的好處,除了解決之前 gae_bingo 帶來的問題以外:

1. 讓系統的負擔減小很多

2. 因為能夠使用到 BigQuery 裡面我們各種不同 source 的資料,AB test 能夠看的結果瞬間多了很多。

心得小結

回顧以上介紹的三種收集資料的管道,我個人認為第二項,把資料從 Server Logging 到外部資料庫是初期很關鍵的工作。難度不高,但是已經能做很多不同的分析了。再這邊分享一個「設計 Logging 的 Table 」的心得,我們的作法是先確定邊界條件:確認 Logging 後的資料可以恢復任何一個時間點網站情況的 Snap Shot,第二個考量的是每個欄位的可讀性,第三點是資料欄位越少越好。

舉例來說,我們有教練身分、學生身分和班級群組:一個教練和學生是多對多的關係,教練又可以把多個學生歸類為一個班級方便管理。當初設計教練、學生建立關係的 Logging 的時候,就要確保只要我們有 2016 年 1 月 1 號全網站教練、班級、學生三者之間的關係,從此之後我們可以藉由 Logging 而得的資料,去重現 2016 年之後任意時間點的教練、班級、學生關係。用這樣的作法來確保收集的資料欄位的完整性。

這樣林林總總,總算把網站前前後後上上下下的資料都統整到資料庫(BigQuery) 了,但是離「讓大家都可以得心應手地處理數據」這個目標還有一大節差距。

首先,資料的來源不一、系統的 Bug、再加上一些外部匯入的資料,造成資料內容上有許多的矛盾和不一致。此外,在軟體組做資料分析的成員增加後,更有許多溝通和上手各個不同資料表的困難,因此資料後續的處理和各種使用的管道也是格外重要,這部份會在(下)篇中提到。

均一資料架構與應用(下)

前情提要

在 (上) 的時候我們分享了均一如何從 DB 、 server 、 client 端把資料導入我們主要處理資料的 Big Query,另外再加上 AB test。之後將分享如何把資料做整理,最後再根據適合的管道投放給有不同需求的對象。

匯入資料整理

經由不同管道匯入的資料需要經過整理後才方便使用,根據以下幾點理由:

1. 許多不同管道有匯入同一資料的情形(ex. 使用者縣市位置:有某些 email 可以反查、有些 ip 可以從學網反查、有些使用者有自填、最後 GA 也會有一個參考值)

2. 許多不同管道匯入的資料表其實圍繞著同一個主題(ex. 教練派任務給學生),整合起來使用更方便。

3. 從 DB 匯入的資料表有些是系統資訊,資料分析不需要用到。

4. 從 DB 匯入的資料有些是其資料格式獨有的 repeated field,在後續使用 ORM 的時候會有問題(見後文)

5. 一些欄位命名不當造成混淆、資料表在匯入時的資料格式限制(ex. 系統的時間是 UTC 而不是 GMT)

因此我們在 Jenkings 設定了一個工作排程,目前是每週會把個管道的資料表做一次整合,在符合 Tidy 原則的情況下,整合成約 20 張資料表,之後後續的分析使用希望都是依據這些資料表,軟體團隊也比較好續控管資料的品質,也方便跟外部單位做資料分析和研究上的合作。

建構資料 DashBoard 給非技術人員使用

均一初期使用的資料呈現工具是 Google spread sheet (路線5),最近嘗試把它搬到 Metabase 上面。(文章為 2017 時,2018 後已全面改用 Metabase)

當初選擇 Google spread sheet 的原因如下:

1. 建構資料 Dash Board,初期需要很多的嘗試 (不知道自己真正要看的是什麼、生了很多資料表最後卻無法連接到行動),因此需要一個容易上手、有大彈性做改動的平台,多做嘗試 (Running Lean 的作法) → 排除一些較大型 BI 系統。

2. 因為對像是非技術人員,希望呈現頁面是他們容易理解互動的。

3. 需要容易和 big query 對接 (ref. 其他和 BigQuery 的第三方合作產品)

4. 因為不確定成效如何,想找一個免費或夠便宜的。

我們在 2016 年暑假找過許多 big query 第三方合作產品,根據以上條件沒有找到適合的,反而是 Google spread sheet,同時兼顧以上幾個優點,當然,因為它本身的使用情境(見下圖說明),使用上也並不那麼方便。因此,最近我們轉而使用 Metabase 的主要原因如下:

1. 直接使用 big query language 即可, Google spread sheet 還需要搭配 Google 自創的 app script。

2. Metabase 下參數更容易

3. Metabase 作圖更方便

4. Metabase 的頁面較美觀

5. Google spread sheet 不方便做版控

我們將常用的query 條件,進行可視覺化的面板選項選取,當欄位完成後,按下 send query 按鈕(可自行設計) 靠著指令編輯器選取,將各個欄位值組合成Query 字串,傳給Bigquery 進行資料擷取,比較常見的是將值放入 where 的用法,例如:如果我將地區設定為 ‘新北’,那麼會在某一段 Query 內部放入一個 「WHERE CITY == ‘新北’ 」這樣的概念。

經過BigQuery 送回的資料,回傳後顯示如上。

Metabase 只負責送出 query,再接收回傳值,本身不負責內容運算, 每次的回傳結果,可直接做圖,或存成表格,將這些結果個別儲存在 dashboard 上,隨時可以檢視。另外 Matabase 的 query 提供安插變數功能,非常方便。附上 Metabase 的 Github

建構 ORM 方便 Query Code 的管理和重複利用

在使用 query language 進行資料分析的時候,query code 只要一複雜 (query 裡面有 sub-query 裡面有 sub-query…),就會產生以下幾個問題:

1. 很難 debug

2. 之後很難重複使用

3. query 上的成果難和他人共享

因此我們最近開始導入 ORM(Object Relational Mapping) (路線 6) 來試著解決問題。

Big Query 目前沒有提供和 ORM 連結的服務,我們使用 Ibis,Ibis 可以把 ORM 編譯成 Impala query code ,我們寫了一個很醜的文字轉換方程式,把 Impala 轉成 sql standard,最後從 Pandas 的 gbq 介面把 sql standard code 丟到 Big Query 上面,成功得到回傳的 Pandas dataframe,來做後續的資料處理。我們把這整個過程包成一個 package 在 github 上面,叫做 big-orm,歡迎大家一起使用。

未來希望以此為基礎,幫助工程師建立可共享和重複使用的資料分析成果,預期也可以開始做資料分析的 Code Review 了!

心得小結

在 (下) 篇我們簡短介紹均一的資料從匯入 Big Query 之後,我們統整,再藉由不同管道匯出給有不同需求的人做使用。

你很容易就會發現,我們開發的套件,或是一些工具的使用方式都很簡陋、很粗糙。因為我們想要先把整個路程(從原始資料的收集到分析到最終做決策影響行動)建構起來,把這整個資料的處理到應用過程視為一個系統,之後在分析資料做決策或建構機器學習功能(我們分析資料的目的)時,再不斷回過頭去檢視系統哪些地方是需要改進的,是有效幫助我們達到最後目標的關鍵。我們認為這會比一開始花好幾倍的時間建構出一個完整的系統,最終卻發揮和我們真正的需求有出入來得有效率。

希望這兩篇文章,對於想要自行建構資料處理系統的團隊有幫助!如果針對裡面那個部分的技術和作法有疑問或建議,都很歡迎大家來彼此認識討論

--

--