dbt Analyses 與 Exposures:管理臨時性分析查詢與資料下游依賴
在 dbt 的開發旅程中,我們主要關注的是 Models,那些最終會在資料庫中建立成 Table 或 View 的物件。然而,數據團隊的工作不僅止於建立資料表,我們還經常需要:
- 撰寫臨時性的分析 SQL (Ad-hoc queries),這些查詢需要引用現有的 Models,但不需要被寫入資料庫。
- 管理資料的「消費者」,例如 BI 儀表板 (Dashboards)、機器學習模型或外部應用程式,並追蹤它們與 dbt Models 的依賴關係。
這兩項需求,分別由 dbt 的 Analyses 與 Exposures 功能來滿足。
dbt Analyses:分析師的強力草稿紙
Analyses 是 dbt 專案中一個專門存放「分析型 SQL」的目錄 (預設為 analyses/)。放在這裡的 SQL 檔案具有以下特性:
- 支援 Jinja 與 dbt 功能:你可以使用
{{ ref('model_name') }}、{{ source(...) }}以及任何自定義的 Macros。這意味著你的分析查詢可以隨著 Models 的改名或邏輯變更而自動更新,不用手動維護。 - 版本控制:這些查詢是專案的一部分,可以被 Git 追蹤與管理。
- 不會被執行 (Materialized):這點最重要。執行
dbt run時,dbt 不會在資料庫中執行這些 SQL,也不會建立任何 View 或 Table。它們純粹存在於程式碼庫中。 - 可以被編譯:透過
dbt compile,dbt 會將包含 Jinja 的原始碼解析成可執行的純 SQL。
為什麼需要 Analyses?
在沒有 Analyses 的情況下,分析師通常會把 SQL 存在自己的電腦文件夾或像 Notion 這樣的筆記軟體中。當 dbt model (例如 fct_orders) 修改了欄位名稱,這些散落在各處的 SQL 就會報錯 Fail。
使用 Analyses 的好處:
- 單一真理來源:所有依賴 dbt models 的查詢都集中管理。
- 便於審查 (Review):複雜的分析邏輯可以透過 Pull Request 讓同事審查,確保邏輯正確。
- 測試邏輯:在正式建立 Model 之前,可以先在 Analyses 中撰寫 SQL 驗證邏輯與數據結果。
如何使用 Analyses
假設我們想計算「2023 年每月的營收與訂單數」,這是一個一次性的分析需求,不需要建表。
- 在
analyses/目錄下建立一個檔案,例如monthly_revenue_analysis.sql。 - 撰寫 SQL,並使用
ref()來引用已經整理好的 Model:
-- analyses/monthly_revenue_analysis.sql
with monthly_data as (
select
-- 使用 date_trunc 函數將日期取至月份
date_trunc('month', order_date) as order_month,
count(order_id) as total_orders,
sum(amount) as total_revenue
from {{ ref('fct_orders') }} -- 引用 fct_orders model
where status = 'completed'
group by 1
)
select *
from monthly_data
order by order_month desc
- 編譯 SQL:
在終端機執行:
dbt compile
- 取得結果:
dbt 會將編譯後的 SQL 檔案輸出到 target/compiled/{project_name}/analyses/monthly_revenue_analysis.sql。
檔案內容會將 {{ ref('fct_orders') }} 替換成實際的資料表名稱 (例如 analytics.dbt_alice.fct_orders)。你可以直接複製這段 SQL 到你的 SQL Client (如 DBeaver) 或 BI 工具中執行。
dbt Exposures:定義資料的下游應用
當你的 dbt 專案日益壯大,擁有數百個 Models 時,一個常見的挑戰是:「如果我修改了 dim_customers 這個 table,會不會弄壞行銷部門的 Looker 報表?」
dbt 本身只知道 Models 之間的依賴關係 (Lineage),但它不知道 dbt 之外的世界。Exposures 就是用來填補這個資訊缺口的。它允許你在 dbt 專案中宣告「外部的下游相依性」,將 Dashboard、ML 模型或反向 ETL 流程納入 dbt 的 Lineage Graph 中。
Exposures 的用途
- 影響範圍分析 (Impact Analysis):在修改程式碼前,查看 Lineage Graph 就能知道變更會影響哪些 Dashboard。
- 文件化與目錄:讓團隊成員知道數據最終被用在哪裡,以及由誰負責 (Owner)。
- 整合應用:某些進階工具 (如 dbt Cloud 的 Dashboard Status Tile) 可以利用這些資訊,直接在 Dashboard 上顯示資料的新鮮度或品質狀態。
如何定義 Exposures
Exposures 定義在 .yml 檔案中 (通常建議放在 models/ 目錄下的相關業務資料夾內,或是獨立的 _exposures.yml 檔案)。
以下是一個完整的 Exposure 定義範例:
version: 2
exposures:
- name: executive_dashboard
label: '高階主管營收儀表板' # 在文件中顯示的名稱
type: dashboard # 類型:dashboard, notebook, analysis, ml, application
maturity: high # 成熟度:high, medium, low
url: https://metabase.company.com/dashboard/123
description: >
這是 CEO 與 CFO 每週一會議使用的主要報表,
包含每日營收趨勢與 top 10 產品銷量。
# 定義依賴關係:這個 Dashboard 用到了哪些 dbt models
depends_on:
- ref('fct_orders')
- ref('dim_customers')
- ref('dim_products')
- source('raw_google_analytics', 'traffic') # 也可以依賴 source
# 定義負責人資訊
owner:
name: Data Team
email: data@company.com
屬性說明
- type: 描述下游應用的類型,常用的有:
dashboard: BI 儀表板 (Tableau, Metabase, Superset 等)。notebook: Jupyter Notebook 或 Hex 等筆記本。application: 網站或後端服務。ml: 機器學習模型。
- maturity: 描述這個應用的重要程度:
high: 關鍵任務,不能隨意壞掉。medium: 重要但非緊急。low: 實驗性質或已棄用。
- depends_on: 最關鍵的部分,列出此 Exposure 查詢了哪些
ref(Models) 或source。這建立了連線。 - owner: 提供聯絡人資訊,當 Model 出問題時知道該通知誰。
在 dbt Docs 中檢視
定義好 Exposure 後,執行 dbt docs generate 並開啟 dbt docs serve。
在 Lineage Graph (血緣關係圖) 中,你會看到最右側出現了橘色的 Exposure 節點。
這讓數據工程師可以清楚地看到:Source -> Staging -> Marts -> Exposure (Dashboard) 的完整資料流向。
總結
| 特性 | Analyses (分析) | Exposures (暴露/下游) |
|---|---|---|
| 主要用途 | 寫 Ad-hoc SQL、測試邏輯 | 記錄資料的消費者 (Dashboard 等) |
| 產出物 | 編譯後的 SQL 檔案 | dbt docs 中的節點與說明 |
| 是否建表 | 否 (不會寫入 DB) | 否 (純 Metadata 定義) |
| 是否可執行 | 需透過 dbt compile 取得 SQL | 僅作為文件與 Lineage 展示 |
| 核心價值 | 讓臨時查詢也享有版控與 Jinja 能力 | 解決資料管道「最後一哩路」的可觀測性 |
善用這兩個功能,可以讓你的 dbt 專案從單純的「造表工廠」,升級為涵蓋資料探索與下游依賴管理的完整「數據治理平台」。