Bạn đã bao giờ rơi vào tình trạng có hàng trăm file SQL, không biết file nào chạy trước, file nào chạy sau? Bạn sửa một logic và vô tình làm sập 10 cái dashboard mà không hề hay biết? Bạn ước gì có thể "version control" và "test" code SQL của mình như lập trình viên phần mềm?
Nếu câu trả lời là có, thì dbt (data build tool) chính là công cụ bạn đang tìm kiếm.
dbt đã và đang tạo ra một cuộc cách mạng trong ngành dữ liệu, khai sinh ra một vai trò hoàn toàn mới: Analytics Engineer. Trong bài viết này, chúng tôi sẽ hướng dẫn bạn từ A-Z về dbt, từ khái niệm cơ bản đến việc xây dựng một project hoàn chỉnh.
dbt là gì và tại sao nó không chỉ là "SQL trong folder"?
Về cơ bản, dbt là một công cụ giúp bạn biến đổi dữ liệu trong data warehouse bằng cách áp dụng các best practice của software engineering vào SQL.
Hãy nghĩ về chữ T trong ELT (Extract, Load, Transform). dbt tập trung hoàn toàn vào chữ T đó. Nó không extract, không load dữ liệu. Nó chỉ làm một việc duy nhất và làm rất tốt: biến đổi dữ liệu đã có sẵn trong data warehouse của bạn.
Vậy nó khác gì với việc viết SQL scripts và chạy bằng Airflow?
| Tính năng | SQL Scripts thông thường | Với dbt |
|---|---|---|
| Phụ thuộc | Phải quản lý thủ công (ví dụ: task_1 >> task_2) | Tự động suy ra từ hàm ref() |
| Testing | Phải tự viết script Python/SQL để test | Tích hợp sẵn, dễ dàng khai báo test |
| Tài liệu | Viết riêng trong Confluence/Notion, dễ lỗi thời | Tự động tạo website tài liệu và lineage graph |
| Môi trường | Khó tách biệt dev và prod | Dễ dàng với profiles và targets |
| Tái sử dụng code | Copy-paste, hoặc stored procedures phức tạp | Dễ dàng với macros (sử dụng Jinja) |
| Version Control | Chỉ lưu code, không có ngữ cảnh | Toàn bộ project là code, dễ dàng review qua Git |
dbt cho phép bạn chỉ cần viết SQL, và nó sẽ lo phần còn lại: build dependency graph, chạy các model theo đúng thứ tự, chạy test, và tạo tài liệu.
Các khái niệm cốt lõi của dbt
1. Models
Một model trong dbt chỉ đơn giản là một file .sql chứa một câu lệnh SELECT. Tên file sẽ trở thành tên của table hoặc view trong data warehouse. Đây là bước thực thi của quá trình Data Modeling. Đây là đơn vị cơ bản nhất của dbt.
2. Sources
Khai báo các bảng dữ liệu thô (raw data) đã được load vào warehouse. Việc này cho phép dbt biết được điểm bắt đầu của chuỗi biến đổi và có thể test dữ liệu nguồn.
3. Tests
Cách để đảm bảo chất lượng dữ liệu. Có 2 loại test trong dbt:
- Schema Tests: Các test phổ biến được định nghĩa sẵn (ví dụ:
unique,not_null,relationships). Bạn chỉ cần khai báo trong file.yml. - Data Tests: Các câu lệnh SQL tùy chỉnh để kiểm tra logic nghiệp vụ phức tạp (ví dụ: "tổng doanh thu của các đơn hàng chi tiết phải bằng doanh thu trong bảng tổng hợp").
4. Macros
Các đoạn code có thể tái sử dụng, được viết bằng Jinja. Giống như function trong các ngôn ngữ lập trình, macros giúp bạn tránh lặp lại code (Don't Repeat Yourself - DRY).
5. ref()
Đây là hàm quan trọng nhất trong dbt. Thay vì hard-code tên bảng (ví dụ: SELECT * FROM analytics.stg_customers), bạn sẽ viết SELECT * FROM {{ ref('stg_customers') }}. dbt sẽ tự động:
- Nối đúng tên bảng cho môi trường dev hoặc prod.
- Xây dựng biểu đồ phụ thuộc (lineage graph), biết rằng model hiện tại phụ thuộc vào
stg_customers.
Hướng dẫn cài đặt project dbt từ đầu
Chúng ta sẽ thực hành với dbt-core (bản miễn phí) và kết nối tới Google BigQuery.
Bước 1: Cài đặt môi trường
Bạn cần có Python và pip trên máy.
# Tạo một virtual environment (khuyến khích)
python -m venv dbt-env
source dbt-env/bin/activate
# Cài đặt dbt-core và adapter cho BigQuery
pip install dbt-core dbt-bigquery
Bước 2: Khởi tạo project dbt
dbt init my_first_dbt_project
dbt sẽ hỏi bạn một vài câu hỏi để tạo cấu trúc thư mục ban đầu.
Bước 3: Cấu hình profiles.yml
Đây là file chứa thông tin kết nối tới data warehouse của bạn. File này thường nằm ở ~/.dbt/profiles.yml (bên ngoài project) để giữ bí mật thông tin nhạy cảm.
Một ví dụ cho BigQuery:
my_first_dbt_project:
target: dev
outputs:
dev:
type: bigquery
method: service-account
project: your-gcp-project-id
dataset: dbt_dev # Dataset riêng cho môi trường dev
threads: 4
keyfile: /path/to/your/gcp-keyfile.json
Bước 4: Kiểm tra kết nối
dbt debug
Nếu bạn thấy "All checks passed!", xin chúc mừng, bạn đã sẵn sàng!
Xây dựng dbt project đầu tiên - Tutorial
Giả sử chúng ta có 2 bảng dữ liệu thô trong BigQuery: raw_customers và raw_orders.
Cấu trúc thư mục
Project của bạn sẽ trông như thế này:
my_first_dbt_project/
├── models/
│ ├── staging/
│ ├── intermediate/
│ └── marts/
├── tests/
├── dbt_project.yml
└── profiles.yml (nằm ngoài project)
Bước 1: Khai báo Sources
Tạo file models/staging/sources.yml:
version: 2
sources:
- name: jaffle_shop
description: "Raw data from our e-commerce platform"
database: your-gcp-project-id
schema: raw_data
tables:
- name: raw_customers
- name: raw_orders
Bước 2: Xây dựng Staging Models
Staging models chỉ làm những việc đơn giản: đổi tên cột, ép kiểu dữ liệu, và các phép tính cơ bản. Không join ở lớp này.
Tạo file models/staging/stg_customers.sql:
select
id as customer_id,
first_name,
last_name
from {{ source('jaffle_shop', 'raw_customers') }}
Tạo file models/staging/stg_orders.sql:
select
id as order_id,
user_id as customer_id,
order_date,
status
from {{ source('jaffle_shop', 'raw_orders') }}
Lưu ý chúng ta đã dùng hàm source() để tham chiếu đến dữ liệu thô.
Bước 3: Xây dựng Marts Model
Đây là model cuối cùng, sẵn sàng cho BI tool. Chúng ta sẽ join các staging models lại.
Tạo file models/marts/dim_customers.sql:
with customers as (
select * from {{ ref('stg_customers') }}
),
orders as (
select * from {{ ref('stg_orders') }}
),
customer_orders as (
select
customer_id,
min(order_date) as first_order_date,
max(order_date) as most_recent_order_date,
count(order_id) as number_of_orders
from orders
group by 1
)
select
c.customer_id,
c.first_name,
c.last_name,
co.first_order_date,
co.most_recent_order_date,
coalesce(co.number_of_orders, 0) as number_of_orders
from customers c
left join customer_orders co on c.customer_id = co.customer_id
Lưu ý chúng ta đã dùng hàm ref() để tham chiếu đến các model khác.
Bước 4: Chạy dbt
dbt run
dbt sẽ tự động chạy stg_customers và stg_orders trước, sau đó mới chạy dim_customers.
Đảm bảo chất lượng dữ liệu với Tests
Bây giờ, hãy thêm một vài test để đảm bảo dữ liệu của chúng ta đáng tin cậy.
Mở file models/staging/sources.yml và thêm tests:
version: 2
sources:
- name: jaffle_shop
# ...
tables:
- name: raw_customers
columns:
- name: id
tests:
- unique
- not_null
- name: raw_orders
columns:
- name: id
tests:
- unique
- not_null
- name: status
tests:
- accepted_values:
values: ['placed', 'shipped', 'completed', 'return_pending', 'returned']
Tạo file models/marts/marts.yml để test model cuối:
version: 2
models:
- name: dim_customers
columns:
- name: customer_id
tests:
- unique
- not_null
Bây giờ, chạy lệnh:
dbt test
dbt sẽ tự động sinh ra các câu lệnh SQL để kiểm tra các điều kiện trên. Nếu có test nào thất bại, nó sẽ báo lỗi.
Tự động hóa tài liệu và Lineage
Đây là một trong những tính năng "thần kỳ" của dbt.
Chạy 2 lệnh sau:
dbt docs generate
dbt docs serve
dbt sẽ tạo ra một website tĩnh cho toàn bộ project của bạn. Mở trình duyệt và bạn sẽ thấy:
- Mô tả chi tiết của từng model, từng cột.
- Code SQL của model.
- Kết quả của các data test.
- Và quan trọng nhất: Biểu đồ phụ thuộc (Lineage Graph) cho bạn thấy dữ liệu chảy từ đâu đến đâu.

Để tài liệu phong phú hơn, bạn có thể thêm mô tả vào các file .yml:
models:
- name: dim_customers
description: "One record per customer. Includes lifetime value metrics."
columns:
- name: customer_id
description: "Primary key for the customers table."
tests:
- unique
- not_null
CI/CD đơn giản với GitHub Actions
Để đảm bảo code mới không làm hỏng logic hiện tại, chúng ta có thể thiết lập một quy trình CI/CD đơn giản. Mỗi khi có một Pull Request mới, một job sẽ tự động chạy để test code.
Tạo file .github/workflows/dbt_run.yml:
name: dbt CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
dbt_run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
pip install dbt-core dbt-bigquery
- name: Set up dbt profile
run: |
mkdir -p ~/.dbt/
echo "${{ secrets.DBT_PROFILES_YML }}" > ~/.dbt/profiles.yml
- name: Run dbt deps
run: dbt deps
- name: Run dbt models
run: dbt run
- name: Test dbt models
run: dbt test
Lưu ý: Bạn cần lưu nội dung file profiles.yml vào GitHub Secrets với tên DBT_PROFILES_YML.
Bây giờ, mỗi khi bạn tạo Pull Request, GitHub sẽ tự động chạy dbt run và dbt test để xác nhận code của bạn an toàn trước khi merge.
Kết luận
dbt không chỉ là một công cụ, nó là một triết lý làm việc mới cho các đội ngũ dữ liệu. Bằng cách áp dụng các nguyên tắc của software engineering, dbt giúp bạn xây dựng các quy trình biến đổi dữ liệu một cách đáng tin cậy, có thể mở rộng và dễ dàng bảo trì.
Nếu bạn đang bắt đầu với Modern Data Stack, dbt là một thành phần gần như không thể thiếu. Nó trao quyền cho các data analyst, giải phóng các data engineer khỏi các tác vụ lặp đi lặp lại, và mang lại sự tin tưởng vào dữ liệu cho toàn bộ tổ chức.
Bắt đầu với dbt có thể hơi khó khăn lúc đầu, nhưng lợi ích dài hạn mà nó mang lại là vô cùng to lớn. Chúc bạn thành công trên hành trình chinh phục dbt!




