Tầng staging và mart
Bạn sẽ học được
- Ba tầng model trong một project dbt và việc gì thuộc tầng nào.
- Quy ước đặt tên
stg_,int_,fct_,dim_. - Vì sao staging không được join và mart không được đọc thẳng nguồn.
- Chọn materialization mặc định cho từng tầng.
- Nhận ra dấu hiệu logic bị lặp giữa các mart.
Khái niệm cốt lõi
Một project dbt lớn thường có hàng trăm model. Nếu ai cũng viết model theo cách riêng, sau sáu tháng không ai dám sửa gì. Tầng model là quy ước chung để mỗi file có một chỗ đứng rõ ràng.
| Tầng | Tiền tố | Làm gì | Không làm gì |
|---|---|---|---|
| Staging | stg_ | Đổi tên cột, ép kiểu, lọc bản ghi rác, giải mã giá trị | Join, tính toán kinh doanh, gộp nhiều nguồn |
| Intermediate | int_ | Join, gộp, tính bước trung gian phức tạp | Được người dùng cuối đọc trực tiếp |
| Mart | fct_, dim_ | Bảng sự kiện và bảng chiều phục vụ báo cáo | Đọc thẳng bảng nguồn thô |
Quy tắc quan trọng nhất: staging ánh xạ 1–1 với bảng nguồn. Mỗi bảng nguồn có đúng một model staging. Nhờ vậy khi nguồn đổi tên cột, bạn sửa đúng một file.
Tầng mart chia hai loại:
- Fact (
fct_): một dòng là một sự kiện — một đơn hàng, một lần thanh toán, một phiên truy cập. Có khoá ngoại và số đo. - Dimension (
dim_): một dòng là một thực thể — một khách hàng, một sản phẩm, một cửa hàng. Có thuộc tính mô tả.
Ví dụ chạy được
Cấu trúc thư mục:
models/
staging/
sources.yml
stg_orders.sql
stg_customers.sql
stg_payments.sql
intermediate/
int_orders_enriched.sql
marts/
fct_orders.sql
dim_customers.sql
schema.ymlTầng staging — chỉ làm sạch:
-- models/staging/stg_orders.sql
select
id as order_id,
customer_id,
cast(created_at as date) as order_date,
lower(status) as status,
amount_cents / 100.0 as amount,
coalesce(discount_cents, 0)/100.0 as discount
from {{ source('raw', 'orders') }}
where id is not nullTầng intermediate — nơi được phép join:
-- models/intermediate/int_orders_enriched.sql
select
o.order_id,
o.order_date,
o.customer_id,
c.segment,
c.region,
o.amount - o.discount as net_amount
from {{ ref('stg_orders') }} o
left join {{ ref('stg_customers') }} c using (customer_id)Tầng mart — tổng hợp cho báo cáo:
-- models/marts/fct_orders.sql
select
order_date,
segment,
region,
count(*) as orders,
sum(net_amount) as revenue
from {{ ref('int_orders_enriched') }}
where status in ('paid', 'shipped')
group by 1, 2, 3Cấu hình materialization theo tầng trong dbt_project.yml:
models:
dbt_shop:
staging:
+materialized: view
intermediate:
+materialized: view
marts:
+materialized: tableVới 1.000.000 đơn hàng, staging dạng view tốn 0 giây lưu trữ và luôn phản ánh nguồn mới nhất. Mart dạng table tốn khoảng 40 giây build mỗi lần chạy nhưng dashboard chỉ đọc một bảng đã gộp sẵn, thay vì join lại 1.000.000 dòng mỗi lần tải trang.
Vì sao phải tách tầng
Tái sử dụng. Nếu ba mart đều cần "đơn hàng đã trừ giảm giá", logic đó nằm một lần ở int_orders_enriched. Khi quy tắc giảm giá đổi, sửa một chỗ.
Cô lập thay đổi. Nguồn đổi tên amount_cents thành amount_minor, chỉ stg_orders phải sửa. Mọi mart phía sau không biết gì.
Kiểm thử đúng chỗ. Test kỹ thuật (unique, not_null, relationships) đặt ở staging. Test nghiệp vụ (tổng khớp, không âm, không vượt ngưỡng) đặt ở mart.
Đọc được đồ thị. Nhìn lineage thấy ngay dữ liệu đi từ nguồn nào, qua bước nào, tới báo cáo nào.
Dấu hiệu thiết kế sai
| Dấu hiệu | Vấn đề | Cách sửa |
|---|---|---|
stg_ có join | Trộn hai trách nhiệm | Chuyển join sang int_ |
Ba mart cùng viết lại một case when | Logic lặp | Đưa lên int_ |
Mart đọc {{ source(...) }} | Bỏ qua lớp làm sạch | Đọc qua stg_ |
| Một mart dài 400 dòng | Không tách bước | Chia thành hai int_ |
stg_ lọc theo điều kiện kinh doanh | Staging không còn 1–1 | Chuyển bộ lọc sang mart |
Thực hành
- Liệt kê các bảng nguồn của bạn và tạo một
stg_cho mỗi bảng. - Chuyển một phép join đang nằm trong mart xuống
int_. - Đặt materialization
viewcho staging,tablecho mart trongdbt_project.yml. - Chạy
dbt build --select stagingrồidbt build --select marts. - Mở
dbt docs serve, xem lineage và đếm số tầng từ nguồn tới một mart.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách sửa |
|---|---|---|
| Sửa nguồn phải sửa 5 model | Mart đọc thẳng source | Cho mart đọc qua stg_ |
| Hai báo cáo ra số khác nhau | Logic join lặp ở hai mart | Gom vào một int_ |
| Dashboard chậm | Mart để view trên nguồn lớn | Đổi mart sang table |
| Dữ liệu mart trễ | Staging là table build theo lịch | Đổi staging sang view |
| Không tìm được nguồn của cột | Tầng trung gian đặt tên khác nhau | Giữ tên cột gốc ở staging |
Tóm tắt
- Ba tầng: staging làm sạch, intermediate join và tính toán, mart phục vụ báo cáo.
- Staging 1–1 với bảng nguồn, không join, không lọc nghiệp vụ.
- Fact là sự kiện, dimension là thực thể.
- Materialization mặc định: staging
view, marttable. - Logic lặp giữa các mart là dấu hiệu cần thêm tầng intermediate.
Use ← → to move between lessons