dbt(Data Build Tool) Part 1 — Introduction
近年在硬體儲存與運算設備的進化、雲的誕生等,資料量日趨廣大,為各個產業對轉型帶來更多可能應用的價值。在資料領域中很常出現的一句話就是Garbage in, Garbage out ,當擁有了大量的資料,在資料工程面該如何做出品質更好的資料前處理帶給分析人員產出更好的價值,漸漸成為不同產業相當重視的議題。
現代分析人員與資料科學家中用 Python 與 SQL 做資料提取到分析,已經是入門資料相關工作很通用的基本能力,如果在資料工程中可以支援這兩樣,或許會讓團隊溝通的過程中輕鬆許多且容易上手。
基於以上,可以意識到處理 ETL ( 提取、轉換、載入) 或 ELT 過程變得相當重要,工具在市面上的選擇眾多,但是用到不合適的工具可能會為資料工程人員所支援的業務單位及資料做決策的能力產生負面的影響。而資料工程人員需要經過討論與調查,並考量到公司與團隊的特性選取合適的工具,將其引進解決問題,使資料利用達到更好的價值。
在資料團隊中可能會遇到的挑戰:
1. 如何將 SQL 自動化。
2. 如何對 SQL 版本控制。
3. 過高的學習曲線。
4. 資料的文件化。
5. 資料品質測試。
6. 資料表 schema 的管理。
過往在 KKday 使用的儲存資料庫多在 AWS 上,但是在應用端 GCP BigQuery 的查詢速度更快速、應用變得更容易、彈性大、費用低廉,
因此在 Data Silo -> Data Lake -> Data Warehouse -> DataMart,基本流程中團隊構建了 Python ETL Library 透過 Apache Airflow 調用 AWS、GCP、dbt 等服務讓團隊在不管是業務端或第三方的資料到應用端流程自動化變得更容易,此篇介紹的是 dbt 的部分。
dbt 能帶給你什麼?
dbt 是一個 Open Source 的 Framework ,將模組化 SQL 與軟體工程最佳實踐相結合,使資料轉換變得可靠、快速和有趣。
dbt(資料構建工具)使具有資料分析人員技能的人可以使用簡單的 SQL 語句來建立、轉換與驗證 Data Warehouse 中的資料,有效地使用程式碼創建整個過程。可以使用 SQL 編寫自定義業務邏輯、自動化資料品質測試、部署程式碼,並提供可信任的資料與程式碼並行的資料文檔。
簡單說, dbt(資料構建工具)期望讓資料分析人員較輕鬆做到工程師能做的事情,並更好推動整個分析工程的工作流程,也在資料工程團隊在 Cloud 與 Data Warehouse 的應用上有靈活的表現。
dbt的優點
- dbt 是一個資料構建的 Open Source 工具,讓資料相關人員較輕鬆透過SQL 語句轉換資料到 Table 與 View 並做到一些軟體工程人員可以做到的事情。
- dbt 在 ELT 中非常擅長 T 的部分
- 沒有陡峭的學習曲線。
- 輕鬆做到版本控制。
- 除了熟悉 SQL 和 Python 的基本知識外,不需要特定的技能。可以透過模板並利用 dbt init 自動生成,為所有資料管道標準化。
- 多元的 DB Support,ex: PostgreSQL、BigQuery、Redshift、Snowflake 等。
dbt 的缺點
- dbt 擅長 ELT 在 T 的部分,因此需要其他工具去協助你的 EL。
- dbt 在資料品質部分提供少量支援,但多數時間已經夠用,若需要更多的資料品質檢查,可以利用資料品質工具 dbt-expectations 或 great expectations 去彌補。
- dbt 主要是 SQL based,因此與具有互動的 UI 工具比較,在可讀性方面提供的少一點。
dbt 基本專案結構
若是想嘗試 dbt 的話,可以將官方提供的 github 專案 clone 下來 dbt-starter-project 並可以參考 getting start with dbt core 在本地做嘗試。
本篇介紹 dbt 的基本專案結構是由 dbt-starter-project 所更改,其資料夾結構如下圖:
models: 存放 .sql 檔案,寫入需要用到的 SQL 語句,當使用 dbt run 可以在你的 Data Warehouse 建立此 model。
tests: 測試 dbt 中的 models 或其他資源做出 assert,當運行 dbt test 的時候則可以知道哪些是通過,哪些是失敗的。
marcos: 在 dbt 中可以使用 jinja 模板語言結合,而 marcos 則是可以多次重複使用的程式碼,類似於程式語言中的函數,若有重複的程式碼則可以好好的多加利用 marcos 。
snapshots: 有時候分析師需要 “look back” 也就是有些動態表的某些歷史資料。而 snapshots 紀錄了表隨時間的變化。
analysis: dbt 的 model 概念使資料團隊可以輕鬆地進行版本控制和協作進行資料轉換。 但有時,某個 SQL 語句並不完全適合 dbt model。 這些更具“分析性”的 SQL 可以使用 dbt 的分析功能在 dbt 項目中進行版本控制。
dbt_project.yml: 有這個設定檔案,dbt 才知道現在此專案是 dbt 的專案,裡面也可以設定一些重要資訊。
dbt 基本工作流程
Develop: 撰寫模組化的程式碼,專注在 SQL 語句上。
Test & Documents: 撰寫資料品質測試與資料文件描述。ex: 某個欄位要是 unique 或是 not null,提前預防資料品質問題。
Deploy: 經過設定後部署,供給後續使用者使用,也可以配合相關任務排程工具調用 -> Apache Airflow、Apache Nifi、Apache Beam。 ex: BI、ML、Anaylysis、anyone who needs。
Schema
Target Schema
在 dbt 中需要透過 profiles.yml 定義不同的環境與其資訊,也就是定義預設的 schema (在 BigQuery 中稱為 dataset)。此預設的 schema 又稱為 target schema。
Custom Schema
預設情況下,所有 dbt models 會被建立在指定於 target 中的 schema。 當具有大量models 的 dbt 項目中,嘗試建立一些 models 在不同的 schema 中可能比只建立在 target schema 好, 這樣有助於在邏輯上區分不同階段的 models 最後將 models 整合在一起。
- 基於業務單位來對 models 進行分組建立 schema。ex: Core、Finance、RD、Marketing。
- 在 staging schema 隱藏其中間過程的 models,使用者僅能使用 analytics schema 或是 mart schema 做查詢。
dbt 一般 schema 建立的情況:
當 dbt 建立在資料庫建立關聯 (table/view),
-> {{ database}}.{{ schema }}.{{ identifier }}
-> database_a.data_warehouse_analysis_record.members_orders_mapping
- 如果未指定 custom schema,則 target schema 為 ( {{ target.schema }})。
- 若指定 custom schema,如果指定了 custom schema,則 target schema 為 ( {{ target.schema }}_{{ custom_schema }})。
dbt_project.yml
# models in `models/data_warehouse will be rendered to the
# "analysis_record" schema
models:
data_warehouse:
ANALYSIS_RECORD:
+schema: analysis_record
以 BigQuery 為例,一個 schema 為一個 dataset,可以視為
{{ schema }}.{{ identifier }} = {{ dataset }}.{{ table }}。
假設今天一個單純只有 target schema 為 data_lake,當資料要導入 BigQuery 時所有 table 會全部放在 data_lake 這個 dataset 底下,dataset 與 table 可能像是下面:
# only 1 dataset - data_lake
data_lake.analysis_record_order_dashboard
data_lake.analysis_record_flight_dashboard
data_lake.transform_flight
data_lake.transform_airport
而另一個有指定 custom schema 為 data_warehouse_{{ schema }},dataset 與 table 可能像是下面:
# dataset1 - data_warehouse_analysis
data_warehouse_analysis.order_dashboard
data_warehouse_analysis.flight_dashboard# dataset2 - data_warehouse_transform
data_warehouse_transform.flight
data_warehouse_trasnform.airport
基本範例設定
dbt 建立於 models 之間的相依關係是有向無環圖(DAG) — 圖中的每個節點代表一個 model,當執行 dbt 時會根據 SQL 中的 ref 定義去建立 DAG 決定 model 的執行順序,而 DAG 不管左到右的路要怎麼走,最後都會在最右邊的任務結束。
當 dbt 運行時,model 按照 DAG 指定的順序執行,無需明確定義 model 的執行順序。 在分階段 transform 時建立 model 還可以減少了重複 SQL 的語法,因為單個 transform(ex: rename columns)可以共享給多個下游的 model 。
假設今天 KKday 需要將會員資料與會員訂單合併到 Data WareHouse 做應用。
SQL 如下:
materialized 可以指定建立的表要是 table 或是 view。
models/ANALYSIS_RECORD/members_orders_mapping.sql{{
config(
alias = 'members_orders_mapping',
materialized = 'views'
) }}select a.member_id, a.member_name, b.order_id, b.order_time
from data_lake.members_profile a
join data_lake.members_orders b
on a.member_id = b.member_id
profiles.yml 檔:
下面範例透過 yml 定義欄位詳細描述資訊與需要測試的規則,像是會員編號基本上一定是唯一且不能是空值。
models/schema/members_orders_mapping.yml
version: 2
models:
- name: members_orders_mapping
description: 會員與訂單詳細資料
columns:
- name: member_id
description: 會員編號
tests:
- unique
- not_null - name: member_name
description: 會員名稱
tests:
- not_null - name: order_id
description: 訂單編號 - name: order_time
description: 訂單下訂時間
KKday 過往的困難與解決
一般在做 data transform 的時候,經常會有兩種做法與常見問題:
- 撰寫 Python 或 其他程式語言的程式碼,從資料源取得資料並做 transform (通常搭配 pandas 與 sqlachemy ORM 工具)後再存回 DB。
問題1: 需要懂某個程式語言才能維護。
問題2: 程式碼與 SQL 語句可能會交錯不易於閱讀或結構不好統一。 - 完全透過 SQL 語句做 data transform。
問題1:SQL 語句往往疏於管理,難以維護。
問題2:仍需要透過其他程式語言來將其自動化。
而 dbt 使 KKday 在 data transform 時解決過往常見的問題:
- 透過 test 的功能做資料驗證提前發現一些資料問題點。
- 明確的 SQL 定義:讓團隊在這塊不透過其他程式語言。只用 SQL 語句即可管理將其自動化,減少人工執行與程式碼維護成本,
- 解決 SQL 程式碼版本控管:可以使用 Git 來控管 dbt 相關專案,其中包含 SQL 程式碼。
- 資料描述定義:撰寫好資料的描述,當團隊不同開發者或是分析人員需更改、取用的時候能快速上手。
- 設定檔易於設定:學習曲線降低且資料工程團隊將 dbt 完整架構好後,整體專案的架構使分析人員也易於上手。
What’s Next?
希望讀者可以透過此篇文章了解到 dbt 此工具是在做什麼,評估對個人或團隊的優劣,是否需要引進,架構出對團隊與公司有幫助的 data stack。
下一篇文章將講解目前 dbt 在 KKday 資料工程團隊的應用、架構說明。