如何保障數倉數據品質?
導讀
有贊數據報表中心為商家提供了豐富的數據指標,包括30+頁面,100+數據報表以及400+不同類型的數據指標,它們幫助商家更合理、科學地運營店鋪,同時也直接提供分析決策方法供商家使用。並且,每天在跑的底層任務和涉及的數據表已經達到千級別。
面對如此龐大的數據體系,作為測試如何制定品質保障策略呢?這篇文章將從:1.有贊數據鏈路 、2.數據層測試、 3.應用層測試、 4.後續規劃這四個方面展開。
一、有贊數據鏈路
1、數據鏈路介紹
首先介紹有贊的數據總體架構圖:
自頂向下可以大致劃分為應用服務層、數據網關層、應用存儲層、數據倉庫,並且作業開發、元數據管理等平台為數據計算、任務調度以及數據查詢提供了基礎能力。
以上對整體架構做了初步的介紹,對於品質把控來說,最核心的兩個部分是:數據倉庫以及數據應用部分。因為這兩部分屬於數據鏈路中的核心環節,相對於其他層級而言,日常改動也更為頻繁,出現問題的風險也比較大。
二、數據層測試
1、整體概覽
首先,針對數據層的品質保障,可以分成三個方面:數據及時性、完整性、準確性。
2、 數據及時性
數據及時性,顧名思義就是測試數據需要按時產出。及時性重點關注的三個要素是:定時調度時間、優先順序以及數據deadline。其中任務的優先順序決定了它獲取數據計算資源的多少,影響了任務執行時長。數據deadline則是數據最晚產出時間的統一標準,需要嚴格遵守。
這三要素中,屬於「普世規則」且在品質保障階段需要重點關注的是:數據deadline。那麼我們基於數據deadline,針對及時性的保障策略就可分為兩種:
- 監控離線數據任務是否執行結束。這種方式依賴於有贊作業開發平台的監控告警,若數據任務在deadline時間點未執行完成,則會有郵件、企微、電話等告警形式,通知到相應人員。
- 檢查全表條數或者檢查分區條數。這種方式依賴介面自動化平台,通過調用dubbo介面,判斷介面返回的數據指標是否為0,監控數據是否產出。
其次我們可以關註失敗、重試次數,當任務執行過程中出現多次失敗、重試的異常情況,可以拋出告警讓相關人員感知。這部分的告警是對deadline告警的補充,目前在有贊作業開發平台上也有功能集成。
3、數據完整性
數據完整性,顧名思義看數據是不是全,重點評估兩點:數據不多、數據不少。
-
數據不多:一般是檢查全表數據、重要枚舉值,看數據有沒有多餘、重複或者數據主鍵是否唯一。
-
數據不少:一般是檢查全表數據、重要欄位(比如主鍵欄位、枚舉值、日期等),看欄位的數值是否為空、為null等。
可見數據完整性和業務本身關聯度沒有那麼密切,更多的是數倉表的通用內容校驗。所以從一些基礎維度,我們可以將測試重點拆成表級別、欄位級別兩個方向。
表級別完整性:
-
全表維度,通過查看全表的總行數/表大小,若出現表總行數/總大小不變或下降,說明表數據可能出現了問題。
-
分區維度,通過查看當日分區表的數據行數/大小,若和之前分區相比差異太大(偏大或偏小),說明表數據可能出現了問題。
目前有贊元數據管理平台已集成相關數據視圖:
欄位級別完整性:
- 唯一性判斷:保證主鍵或某些欄位的唯一性,防止數據重複導致和其他表join之後數據翻倍,導致最終統計數據偏大。
比如判斷ods層訂單表中的訂單號是否唯一,編寫sql:
select
count(order_no)
,count(distinct order_no)
from ods.xx_order
若兩者相等,則說明order_no值是表內唯一的;否則說明order_no表內不唯一,表數據存在問題。
- 非空判斷:保證重要欄位非空,防止空數據造成和表join之後數據丟失,導致最終統計數據偏少。
比如判斷ods層訂單表中的訂單號是否出現null,編寫sql:
select
count(*)
from ods.xx_order
where order_no is null
若結果等於0,則說明order_no不存在null;若結果大於0,則說明order_no存在null值,表數據存在問題。
- 枚舉類型判斷:保證枚舉欄位值都在預期範圍之內,防止業務臟數據,導致最終統計結果出現遺漏/多餘的數據類型。
比如判斷ods層訂單表中的shop_type欄位中所有枚舉值是否符合預期,編寫sql:
select shop_type from ods.xx_order group by shop_type
分析查詢結果是否滿足預期,確保不會出現遺漏/多餘的枚舉類型。
- 數據有效性判斷:判斷數據格式是否滿足預期,防止欄位的數據格式不正確導致數據統計的錯誤以及缺失。常見的有日期格式
yyyymmdd
。
一旦出現數據完整性問題,對數據品質的影響很大。所以完整性策略更適用於ods層,因為我們更期望從源頭髮現並解決數據不合理問題,及時止損,避免臟數據進入下游之後,數據污染擴大。
另外,我們看到完整性校驗內容邏輯簡單,且比較固定,稍微進行簡單的抽象就能將其模板化。那麼作為測試,我們更傾向於將數據完整性校驗做成工具。目前有贊「數據形態工具」已經落地,下面給出我的一些思路:
-
針對所有表來說,普世性的規則,比如表主鍵的唯一性。
-
針對不同類型比如數值、String、枚舉、日期格式類型,列舉出常見的數據判斷規則。
-
給每項規則進行等級劃分,比如表的主鍵不唯一,記為critical。String類型欄位的空值比例大於70%,記為warning。
-
根據表數據是否滿足上述這些規則,最終落地一份可視化報告,測試人員可根據報告內容評估數據品質。
4、數據準確性
數據準確性,顧名思義數據要「準確」。「準確」這個概念比較抽象,因為我們很難通過一個強邏輯性的判斷,來說明數據有多准,大部分都存在於感性的認知中。所以準確性測試也是在數據品質保障過程中思維相對發散的一個方向。
經過總結,我們可以從欄位自身檢查、數據橫向對比、縱向對比、code review等方面,去把控數據的準確性,這些測試點和業務的關聯也比較密切。
4.1 自身檢查
數據自身檢查,是指在不和其他數據比較的前提下,用自身數據來檢查準確的情況,屬於最基本的一種檢查。常見的自身檢查包括:檢查數值類指標大於0、比值類指標介於0-1範圍。這類基礎規則,同數據完整性,也可以結合「數據形態工具」輔助測試。
舉個例子,比如針對訂單表,支付金額必然是大於等於0,不會出現負數的情況,編寫sql:
select
count(pay_price)
from
dw.dws_xx_order
where par = 20211025 and pay_price<0
若結果為0,說明支付金額都是大於0,滿足預期;否則若count結果大於0,說明數據存在問題。
4.2 表內橫向數據對比
表內橫向對比可以理解為同一張表內,業務上相關聯的兩個或多個欄位,他們存在一定的邏輯性關係,那麼就可以用來做數據對比。
比如針對訂單表,根據實際業務分析易得:針對任何一家店鋪的任意一款商品,都滿足訂單數 >=下單人數,編寫sql:
select
kdt_id
,goods_id
,count(order_no)
,count(distinct buyer_id)
from dw.dws_xx_order
where par = '20211025'
group by kdt_id,goods_id
having count(order_no)<count(distinct buyer_id)
若查詢結果不存在記錄,則說明不存在 訂單數<下單人數,反向說明訂單數>=下單人數,則符合預期;否則若查詢結果的記錄大於0,則不符合預期。
4.3 表間橫向數據對比
表間橫向對比可以理解為兩張表或多張表之間,其中具有業務關聯或者業務含義一致的欄位,可以用來做數據對比:
-
同類型表之間對比:針對hive里的支付表A和支付表B,裡面都有支付金額欄位,那麼同樣維度下的 表A.支付金額 = 表B.支付金額。
-
多套存儲之間對比:比如有贊數據報表中心針對支付表,應用層存儲分別用到了mysql和kylin,用作主備切換,那麼相同維度下的kylin-表A.支付金額 = mysql-表B.支付金額。
-
多個系統之間對比:跨系統之間,比如有贊的數據報表中心和crm系統,兩個系統都有客戶指標數據,那麼相同維度下的數據報表中心-表A.客戶指標 = crm-表B.客戶指標。
我們深度剖析數據橫向對比的底層邏輯,本質就是兩張表的不同欄位,進行邏輯運算符的比較,也比較容易抽象成工具。目前有贊「數據比對工具」已經落地,下面給出我的一些思路:
-
輸入兩張表,分別設置兩表的主鍵。
-
輸入兩張表中需要對比的欄位,且設置對比的運算符,比如>、=、<。
-
根據設置的規則,最終數據對比通過、不通過的記錄,落地一份可視化報告,測試人員可根據報告內容評估數據品質。
4.4 縱向數據對比
縱向對比就是上下游的數據比較,目的是確保重要欄位在上下游的加工過程中沒有出現問題。
比如數倉dw層存在訂單的明細表,數據產品dm層存在訂單數的聚合表,那麼二者在相同維度下的數據統計結果,應該保持一致。
4.5 code review
首先,在進行code review之前的需求評審階段,我們先要明確數據統計的詳細口徑是什麼,下面舉兩個實際的需求例子。
-
需求1:(錯誤示例)統計時間內店鋪內所有用戶的支付金額。問題所在:需求描述太過於簡潔,沒有闡述清楚數據統計的時間維度以及過濾條件,導致統計口徑不清晰,要求產品明確口徑。
-
需求2:(正確示例)有贊全網商家域店鋪維度的離線支付金額。支援自然日、自然周、自然月。統計時間內,所有付款訂單金額之和(剔除抽獎拼團、剔除禮品卡、剔除分銷供貨訂單)。
明確需求之後,下面詳細介紹code review的一些常見關注點:
1)關聯關係 & 過濾條件
-
關聯表使用 outer join 還是 join,要看數據是否需要做過濾。
-
關聯關係 on 字句中,左右值類型是否一致。
-
關聯關係如果是1:1,那麼兩張表的關聯鍵是否唯一。如果不唯一,那麼關聯會產生笛卡爾導致數據膨脹。
-
where 條件是否正確過濾,以上述需求為例子,關注sql中是否正確剔除抽獎拼團、禮品卡和分銷供貨訂單。
2)指標的統計口徑處理
數據指標的統計涉及到兩個基本概念:
-
可累加指標:比如支付金額,瀏覽量等,可以通過簡單數值相加來進行統計的指標,針對這類指標,sql中使用的函數一般是sum。
-
不可累加指標:比如訪客數,不能通過簡單相加,而是需要先去重再求和的方式進行統計,針對這類指標,sql中一般使用count(distinct )。
3)insert插入數據
-
是否支援重跑。等價於看插入時是否有overwrite關鍵字,如果沒有該關鍵字,重跑數據(多次執行該工作流)時不會覆蓋臟數據,而是增量往表插入數據,進而可能會導致最終數據統計翻倍。
-
插入的數據順序和被插入表結構順序是否完全一致。我們要保證數據欄位寫入順序沒有出錯,否則會導致插入值錯亂。
三、應用層測試
1、整體概覽
基本的前端頁面 + 服務端介面測試,和一般業務測試關注點是一致的,不再贅述。本篇重點展開「數據應用「測試需要額外關注的地方。
2、 降級策略
- 在頁面新增數據表的時候,需求、技術評審階段確認是否需要支援「藍條」的功能,屬於「測試左移」。
藍條介紹:有贊告知商家離線數據尚未產出的頁面頂部藍條,其中的「產出時間」 = 當前訪問時間 +2小時,動態計算得到。
- 測試比率類指標時,關注被除數 = 0 的特殊場景。在後端code review、測試頁面功能階段,關注該點。目前有贊針對這種情況,前端統一展示的是「-」。
3、 主備策略
遇到有主備切換策略時,測試過程中注意數據正常雙寫,且通過配置,取數時能在主備數據源之間切換。
4、 數據安全
關注數據查詢的許可權管控,重點測試橫向越權、縱向越權的場景。
四、後續規劃
目前在實際項目的數據準確性對比中,數據對比工具因為暫不支援sql函數,所以只能代替50%的手工測試,一些複雜的橫向和縱向數據對比還是需要編寫sql。後續計劃支援sum、count、max、min等sql函數,把工具覆蓋範圍提升到75%以上,大大降低數據對比的成本。
目前「數據形態報告」、「數據對比工具」更多的運用項目測試當中,後續計劃將形態檢查和數據對比做成線上巡檢,將自動化和數據工具相結合,持續保障數倉表的品質。
目前針對sql code review的方式主要靠人工,我們計劃把一些基礎的sql檢查,比如insert into檢查,join on條件的唯一性檢查、欄位插入順序檢查等作成sql靜態掃描,整合到大數據測試服務中,並且賦能給其他業務線。