dbt 專案的結構化設計對於後續維護和擴充至關重要。一個典型的 dbt 專案包含 models、seeds、snapshots、tests 等目錄,用於存放 SQL 轉換邏輯、初始資料、資料快照和測試程式碼。dbt_project.yml 檔案則扮演著專案設定的核心角色,定義了專案名稱、版本、模型路徑、資料來源以及 BigQuery 等資料函式庫的連線資訊。此外,packages.yml 檔案用於管理外部套件依賴,而 profiles.yml 檔案則儲存了不同環境的資料函式庫連線設定,確保資料轉換流程在不同環境中都能順利執行。

在模型建立方面,dbt 提倡分層設計的理念,將模型劃分為 Staging、Intermediate 和 Marts 三個層級,以提升模型的可讀性、可維護性和可測試性。Staging 層主要負責資料清理和初步轉換,Intermediate 層則進行更複雜的資料轉換和整合,Marts 層則提供導向業務的最終資料集。YAML 檔案的運用能有效管理模型的設定,例如物化方式、資料來源等,提升模型組態的靈活性。此外,dbt 提供了 ref() 函式來管理模型之間的依賴關係,簡化了模型的參照和維護,並確保資料轉換流程的正確性。

dbt 專案結構解析

dbt 專案的組織結構對於資料轉換專案的維護性和可擴充套件性至關重要。本篇文章將探討 dbt 專案的標準結構、重要元件以及最佳實踐。

專案結構概述

一個典型的 dbt 專案包含以下關鍵目錄和檔案:

  • models 目錄:存放主要的 SQL 轉換邏輯,建議按業務領域或功能模組劃分子目錄。
  • seeds 目錄:用於儲存 lookup 表相關的 CSV 檔案,這些資料通常不頻繁變更,用於補充源系統中不存在的資料。
  • snapshots 目錄:專門存放 snapshot 模型,用於記錄可變表隨時間的變化,實作 Type 2 緩慢變化維度(SCDs)。
  • target 目錄:編譯後的 SQL 檔案存放處,當執行 dbt rundbt compiledbt test 命令時產生。
  • tests 目錄:用於存放跨多個表的測試邏輯,雖然部分測試會直接寫在模型對應的 YAML 檔案中或透過巨集實作。
  • dbt_project.yml:專案的核心設定檔,定義了專案的基本資訊和執行引數,是辨識一個目錄是否為 dbt 專案的關鍵。

Jaffle Shop 資料函式庫範例

為了便於理解 dbt 的功能和元件,我們使用 Jaffle Shop 資料函式庫作為範例。它包含客戶和訂單兩個主要表格,以及來自 Stripe 的支付資訊。這些資料構成了我們的原始資料層。

Jaffle Shop 資料函式庫 ERD

@startuml
note
  無法自動轉換的 Plantuml 圖表
  請手動檢查和調整
@enduml

圖表翻譯: 此圖示展示了客戶、訂單和支付之間的關聯。一個客戶可以有多個訂單,而一個訂單可以有多個支付記錄。

YAML 設定檔的使用

YAML 是 dbt 中用於定義模型、snapshot、seeds、測試和來源資料等屬性的主要格式。適當地組織 YAML 檔案對於專案的可維護性非常重要。

YAML 檔案組織建議

  • 保持一致性,並清楚記錄組織結構的原因。
  • 平衡集中組態和檔案大小,避免單一檔案過大導致難以管理和 Git 變更追蹤困難。
  • 採用每個資料夾組態一個 YAML 檔案的做法,便於管理該目錄下的模型組態。
  • 將來源資料組態與模型組態分開存放,例如在相同目錄下分別建立 _sources.yml_models.yml

範例結構

root/
├─ models/
│ ├─ staging/
│ │ ├─ jaffle_shop/
│ │ │ ├─ _jaffle_shop_docs.md
│ │ │ ├─ _jaffle_shop_models.yml
│ │ │ ├─ _jaffle_shop_sources.yml
│ │ │ ├─ stg_jaffle_shop_customers.sql
│ │ │ ├─ stg_jaffle_shop_orders.sql

內容解密: 這種結構將檔案、模型組態和來源組態分開,有利於管理和維護。同時,使用下劃線開頭的檔案名稱可以使這些檔案在目錄中優先顯示,便於查詢。

dbt 專案結構與組態管理

dbt(Data Build Tool)是一種流行的資料轉換工具,廣泛應用於資料倉儲和商業智慧領域。瞭解 dbt 專案的結構和組態管理對於有效使用 dbt 至關重要。本文將探討 dbt 專案的關鍵組成部分及其組態方法。

專案結構概述

一個典型的 dbt 專案包含多個目錄和組態檔案,每個部分都有特定的功能。主要的目錄和檔案包括:

  • models:存放資料轉換邏輯的 SQL 檔案。
  • snapshots:用於實作資料的增量捕捉。
  • tests:包含用於驗證資料品質的測試。
  • macros:自定義的宏,用於簡化 SQL 程式碼的編寫。
  • dbt_project.yml:專案的主要組態檔案。
  • packages.yml:定義了專案依賴的外部包。
  • profiles.yml:資料函式庫連線組態(在使用 dbt CLI 時需要)。

dbt_project.yml 組態檔案

dbt_project.yml 是 dbt 專案的核心組態檔案,包含了專案的基本資訊和預設組態。該檔案的關鍵欄位包括:

  • name:專案的名稱,建議與實際專案名稱一致。
  • version:專案的版本,與 dbt 的版本不同。
  • config-version:組態檔案的版本,目前為版本 2。
  • profile:用於連線資料平台的 profile 名稱。
  • model-pathsmacro-paths 等:指定不同型別檔案的存放目錄。
  • target-path:編譯後的 SQL 檔案存放路徑。
  • clean-targets:指定需要被 dbt clean 命令清理的目錄。
  • models:模型的預設組態,例如物化方式。

組態範例

models:
  dbt_analytics_engineer_book:
    staging:
      materialized: view

上述組態指定了 staging 目錄下的模型預設以檢視(view)的方式物化。

packages.yml 與外部包管理

dbt 支援透過外部包來擴充套件功能,這些包可以從 dbt Hub、Git 倉函式庫或本地路徑安裝。packages.yml 檔案用於定義專案依賴的外部包。

安裝外部包

  1. 在專案根目錄建立或編輯 packages.yml 檔案。
  2. 定義需要的包,例如:
    packages:
      - package: dbt-labs/dbt_utils
        version: 1.1.1
      - git: "https://github.com/dbt-labs/dbt-utils.git"
        revision: 1.1.1
      - local: /opt/dbt/bigquery
    
  3. 執行 dbt deps 命令安裝定義的包。

profiles.yml 與資料函式庫連線組態

在使用 dbt CLI 時,需要組態 profiles.yml 檔案來指定資料函式庫連線資訊。該檔案通常位於使用者主目錄下,以避免將敏感資訊提交到版本控制系統。

組態範例

dbt_analytics_engineer_book:
  target: dev
  outputs:
    dev:
      type: bigquery
      method: service-account
      project: [GCP 專案 ID]
      dataset: [dbt 使用的資料集名稱]
      threads: [執行緒數]

#### 內容解密:

上述範例展示瞭如何組態 profiles.yml 以連線到 BigQuery。使用服務賬戶進行身份驗證,並指定了 GCP 專案 ID 和資料集名稱。

dbt 專案結構與模型建立

dbt(Data Build Tool)是一個強大的資料轉換工具,廣泛應用於資料工程領域。在 dbt 專案中,profiles.yml 檔案和模型(Models)是核心組成部分,對於資料轉換和建模至關重要。

profiles.yml 檔案結構

profiles.yml 檔案主要用於組態 dbt 專案的連線設定,包括不同環境下的資料函式庫連線細節。以下是一個典型的 profiles.yml 檔案結構:

  • profile_name:設定檔的名稱,必須與 dbt_project.yml 中的名稱一致。
  • target:指定不同的環境組態,例如開發環境(dev)和生產環境(prod)。
  • type:指定資料平台的型別,如 BigQuery、Snowflake 或 Redshift。
  • database-specific connection details:根據所選的資料平台,組態相應的連線細節,如 BigQuery 的 methodprojectdatasetkeyfile
  • threads:設定 dbt 專案執行的執行緒數,控制平行執行的模型數量。

BigQuery 連線範例

profile_name:
  target: dev
  outputs:
    dev:
      type: bigquery
      method: service-account
      project: your-project-id
      dataset: your-dataset-id
      keyfile: /path/to/bigquery/keyfile.json
      threads: 4

內容解密:

  • profile_name 是你在 dbt_project.yml 中定義的專案名稱。
  • target 設定為 dev 表示使用開發環境的組態。
  • type 指定為 bigquery 表示連線到 BigQuery 資料函式庫。
  • method 使用 service-account 進行身份驗證。
  • projectdatasetkeyfile 是連線到 BigQuery 所需的詳細資訊。
  • threads 設定為 4,表示 dbt 可以同時處理最多 4 個模型的轉換。

dbt 模型(Models)

模型是 dbt 中的核心概念,用於定義資料轉換邏輯。模型通常以 SQL 檔案的形式存在,並儲存在 models 目錄下。一個良好的模型結構應該遵循資料建模(Data Modeling)和模組化(Modularity)的原則。

模型分層結構

dbt 專案中的模型通常分為三層:

  1. Staging Layer:作為資料來源的介面層,主要進行資料清理和初步轉換。
  2. Intermediate Layer:在 Staging Layer 之上進行更複雜的資料轉換和整合。
  3. Marts Layer:最終的資料層,將多個模組化的模型組合起來,形成導向特定業務部門的資料集。

建立第一個模型

首先,在 models 目錄下建立一個名為 staging 的資料夾,並在其中為每個資料來源建立子資料夾,例如 jaffle_shopstripe

接著,在 staging/jaffle_shopstaging/stripe 中分別建立對應的 SQL 檔案,例如 stg_jaffle_shop_customers.sqlstg_stripe_order_payments.sql 等。

stg_stripe_order_payments.sql 範例

select
  id as payment_id,
  orderid as order_id,
  paymentmethod as payment_method,
  case
    when paymentmethod in ('stripe', 'paypal', 'credit_card', 'gift_card')
    then 'credit'
    else 'cash'
  end as payment_type,
  status,
  amount,
  case
    when status = 'success'
    then true
    else false
  end as is_completed_payment,
  created as created_date
from `dbt-tutorial.stripe.payment`

內容解密:

  • idorderidpaymentmethod 分別重新命名為 payment_idorder_idpayment_method 以提高可讀性。
  • 使用 case 陳述式將 paymentmethod 對映到 payment_type,區分為 'credit''cash'
  • status'success' 的付款標記為 true,其餘標記為 false,並儲存於 is_completed_payment
  • 將原始的 created 時間戳記重新命名為 created_date 以便後續使用。

使用 dbt 進行資料轉換的高階組態與實踐

在前面的章節中,我們已經瞭解瞭如何使用 dbt 建立基本的資料模型,並將其物化(materialize)到 BigQuery 中。現在,我們將進一步探討如何使用 dbt 的高階功能來簡化資料轉換流程並最佳化資料模型的組態。

組態模型的物化方式

預設情況下,dbt 將模型物化為檢視(view)。然而,我們可以透過在模型檔案中新增組態區塊來更改這一行為,如下例所示:

{{
  config(
    materialized='table'
  )
}}

SELECT
  id as customer_id,
  first_name,
  last_name
FROM `dbt-tutorial.jaffle_shop.customers`

內容解密:

此組態區塊指定了模型的物化方式。在這個例子中,materialized='table' 表示該模型將被物化為一個表(table)而不是檢視(view)。這種方式對於需要頻繁查詢或需要儲存歷史資料的場景非常有用。

使用 YAML 檔案組態模型

為了更好地管理模型的組態,我們可以使用 YAML 檔案來定義模型的屬性,例如物化方式。這種方法使得組態更加集中和易於管理。

首先,在 dbt_project.yml 檔案中,我們可以設定預設的物化方式:

models:
  dbt_analytics_engineer_book:
    staging:
      +materialized: view

內容解密:

這段 YAML 組態指定了 staging 目錄下的模型預設被物化為檢視(view)。+materialized: view 是 dbt 的語法,用於指定模型的物化方式。

接下來,我們可以為特定的模型建立單獨的 YAML 檔案來覆寫預設組態。例如,為 stg_jaffle_shop_customers 模型建立 _jaffle_shop_models.yml 檔案:

version: 2
models:
  - name: stg_jaffle_shop_customers
    config:
      materialized: table

內容解密:

此 YAML 檔案指定了 stg_jaffle_shop_customers 模型將被物化為表(table),覆寫了 dbt_project.yml 中的預設組態。這種級聯組態的方式使得我們可以在不同層級上靈活地控制模型的物化方式。

建立中間層模型

在處理複雜的資料轉換時,通常需要建立中間層模型來隔離複雜的操作。假設我們的業務需求是分析每個客戶的訂單總金額和不同支付方式的金額。我們可以建立一個名為 int_payment_type_amount_per_order.sql 的中間層模型:

with order_payments as (
  select * from {{ ref('stg_stripe_order_payments') }}
)
select
  order_id,
  sum(
    case
      when payment_type = 'cash' and status = 'success'
      then amount
      else 0
    end
  ) as cash_amount,
  sum(
    case
      when payment_type = 'credit' and status = 'success'
      then amount
      else 0
    end
  ) as credit_amount,
  sum(
    case
      when status = 'success'
      then amount
    end
  ) as total_amount
from order_payments
group by 1

內容解密:

此 SQL 程式碼首先從 stg_stripe_order_payments 模型中選擇所有欄位,然後計算每個訂單的現金支付金額、信用卡支付金額和總金額。使用了 Jinja 的 ref() 函式來參照其他模型,實作了模型的復用和依賴管理。

使用dbt進行資料轉換的進階應用

建立中間表與事實表

在前面的章節中,我們已經討論瞭如何使用dbt建立初始的資料模型。現在,我們將探討如何建立中間表(Intermediate Tables)以及最終的事實表(Fact Tables)和維度表(Dimension Tables)。

建立中間表

首先,我們需要建立一個名為order_payments的CTE(Common Table Expression),它將從stg_stripe_order_payments表中提取資料。這裡使用了dbt的ref()函式來參照上游的資料表或檢視。ref()函式的好處包括:

  • 允許在模型之間建立靈活的依賴關係,並且可以在共同的程式碼函式庫中分享。
  • 在執行dbt執行時,會根據環境組態編譯資料函式庫物件的名稱。
with order_payments as (
  select * from {{ ref('stg_stripe_order_payments') }}
)

建立事實表與維度表

接下來,我們需要建立事實表fct_orders和維度表dim_customers。事實表將包含訂單的詳細資訊,而維度表則包含客戶的相關資訊。

-- dim_customers.sql
with customers as (
  select * from {{ ref('stg_jaffle_shop_customers') }}
)
select
  customers.customer_id,
  customers.first_name,
  customers.last_name
from customers
-- fct_orders.sql
with orders as (
  select * from {{ ref('stg_jaffle_shop_orders') }}
),
payment_type_orders as (
  select * from {{ ref('int_payment_type_amount_per_order') }}
)
select
  ord.order_id,
  ord.customer_id,
  ord.order_date,
  pto.cash_amount,
  pto.credit_amount,
  pto.total_amount,
  case
    when status = 'completed'
    then 1
    else 0
  end as is_order_completed
from orders as ord
left join payment_type_orders as pto ON ord.order_id = pto.order_id

設定dbt專案組態

dbt_project.yml檔案中,我們需要設定模型的預設組態,包括指定不同層級的資料物化方式。

models:
  dbt_analytics_engineer_book:
    staging:
      +materialized: view
    intermediate:
      +materialized: view
    marts:
      +materialized: table

使用dbt來源管理原始資料

在dbt中,來源(Sources)指的是資料平台中可用的原始資料。這些原始資料通常由資料工程團隊使用提取和載入(EL)工具載入到資料平台中。

定義來源

為了更好地管理原始資料,我們可以在YAML檔案中定義來源。這樣做的好處是,當原始資料的位置或表格名稱發生變化時,我們只需更新YAML檔案即可,而無需在多個SQL檔案中進行更改。

-- _jaffle_shop_sources.yml
version: 2
sources:
  - name: jaffle_shop
    database: dbt-tutorial
    schema: jaffle_shop
    tables:
      - name: customers
      - name: orders
-- _stripe_sources.yml
version: 2
sources:
  - name: stripe
    database: dbt-tutorial
    schema: stripe
    tables:
      - name: payment

圖表翻譯:dbt資料流程圖

此圖示呈現了dbt模型之間的依賴關係和資料流程。透過使用ref()函式和定義來源,我們可以清晰地瞭解資料是如何在不同的模型之間流動的。

圖表翻譯: 本圖展示了從原始資料到最終事實表和維度表的資料轉換過程。其中,stg_jaffle_shop_customersstg_jaffle_shop_orders是原始資料表,經過處理後生成了dim_customersfct_orders等最終表格。

內容解密:

  1. 使用ref()函式參照上游資料表或檢視。
  2. 定義來源以管理原始資料。
  3. 建立中間表和最終的事實表與維度表。
  4. 設定dbt專案組態以指定資料物化方式。

透過遵循上述步驟和最佳實踐,我們可以有效地使用dbt進行資料轉換和分析。