Trong kỹ thuật phân tích (analytics engineering), dbt (data build tool) macro cung cấp một cách mạnh mẽ để viết logic SQL động, có thể tái sử dụng thông qua các khối mã dùng chung.
Trong hướng dẫn này, chúng ta sẽ khám phá các khái niệm cơ bản về macro dbt, cách xây dựng chúng bằng Jinja, thực tiễn tốt để dễ bảo trì, và các ứng dụng thực tế, kèm theo ví dụ mã.
Macro dbt là gì?
Macro dbt là các khối mã có thể tái sử dụng được viết bằng ngôn ngữ mẫu Jinja trong dbt, cho phép bạn tạo ra SQL một cách động. Chúng giúp giảm lặp lại và tập trung hóa logic chuyển đổi.
Các macro hoạt động tương tự như hàm trong các ngôn ngữ lập trình truyền thống.
Ví dụ, nếu bạn cần tính một chỉ số cụ thể trên nhiều model, một macro có thể đóng gói phép tính đó, giúp dễ dàng bảo trì và cập nhật hơn.
Macro cũng có thể được lưu trong các package, chẳng hạn như dbt-utils.
Tại sao dùng macro dbt?
Macro mang lại nhiều lợi thế, chủ yếu là:
Giảm dư thừa: Bạn có thể viết một khối logic một lần và dùng lại ở mọi nơi.
Nhất quán: Áp dụng cùng một logic chuyển đổi trên các model mà không cần sao chép thủ công.
Linh hoạt: Macro hỗ trợ tham số, giúp thích ứng với nhiều đầu vào khác nhau.
Chia sẻ liên dự án: Macro được thiết kế tốt có thể được chia sẻ dưới dạng package.
Những lợi ích này dẫn tới codebase gọn gàng, dễ bảo trì và có khả năng mở rộng hơn.
Các khái niệm nền tảng về macro dbt
Để giúp bạn hiểu cách macro hoạt động trong dbt, hãy cùng xem một số khái niệm chính.
1. Tính có thể tái sử dụng
Macro cho phép bạn định nghĩa một phần logic SQL một lần và dùng lại trên nhiều model, test, hoặc thậm chí macro khác.
2. Bộ máy mẫu Jinja
Jinja tích hợp với dbt giúp chèn biến, áp dụng điều kiện, và lặp qua danh sách, tất cả diễn ra trước khi SQL của bạn đến cơ sở dữ liệu. dbt biên dịch mẫu này thành SQL thô, khiến macro không phụ thuộc vào hệ cơ sở dữ liệu.
3. Giới thiệu kỹ thuật lập trình
Macro có thể biến SQL thành một khung có thể lập trình. Chúng cho phép logic, vòng lặp và điều kiện—những thứ mà SQL chuẩn không xử lý linh hoạt bằng.
Tương tự hàm, macro trong dbt có thể nhận đối số (tham số) và có thể được gọi với các đầu vào khác nhau để tạo ra đầu ra khác nhau. Chúng giúp đơn giản hóa các chuyển đổi phức tạp bằng cách chia nhỏ thành các đơn vị nhỏ, có thể tái sử dụng.
Xây dựng macro với Jinja
Tiếp theo, hãy xem cách tự xây dựng một số macro.
Jinja là bộ máy mẫu vận hành macro dbt, cho phép bạn xử lý SQL như văn bản động, có thể lập trình.
Cấu trúc mẫu và dấu phân cách
Để dùng Jinja, bạn sẽ cần các cấu trúc mẫu và dấu phân cách cụ thể.
Dưới đây là một số cấu trúc và dấu phân cách thường dùng:
Biểu thức {{ }}: Chèn biểu thức.
Câu lệnh {% %}: Thực thi câu lệnh.
Chú thích {# #}: Thêm chú thích để dbt bỏ qua.
Trong macro, {{ ... }} dùng cho biểu thức cần xuất ra giá trị (ví dụ: tên cột hoặc phép tính), trong khi {% ... %} dùng cho điều khiển luồng (vòng lặp, if/else, định nghĩa macro). Chú thích Jinja dùng {# ... #} và bị loại bỏ hoàn toàn khi biên dịch.
Đây là ví dụ về cú pháp dùng cho các câu lệnh trong macro:
Chúng ta sẽ dùng Python để tạo một bộ dữ liệu orders nhỏ và nạp vào Postgres (hoặc warehouse bạn chọn).
import pandas as pd
import random
from datetime import datetime, timedelta
from sqlalchemy import create_engine
# Create sample orders dataframe
random.seed(42)
num_rows =20
start_date = datetime(2025,1,1)
data =[]for i inrange(1, num_rows +1):
order_date = start_date + timedelta(days=random.randint(0,30))
ship_date = order_date + timedelta(days=random.randint(1,10))
data.append({'order_id': i,'customer_id': random.randint(100,105),'order_date': order_date.date(),'ship_date': ship_date.date(),'status': random.choice(['pending','shipped','delivered']),'revenue':round(random.uniform(50,500),2),'cost':round(random.uniform(20,400),2)})
df = pd.DataFrame(data)# Load into Postgres
engine = create_engine('postgresql://user:password@localhost:5432/dbt_demo')
df.to_sql('orders', engine, if_exists='replace', index=False)Được hỗ trợ bởi
Lưu ý: Cập nhật chuỗi kết nối cho cơ sở dữ liệu của bạn.
4. Tạo source trong dbt
Thêm nội dung sau vào models/src_orders.yml:
version: 2
sources:
- name: public
schema: public
tables:
- name: ordersĐược hỗ trợ bởi
5. Kiểm tra kết nối và source
dbt debug
dbt run-operation list_relations --args'{"schema_name": "public"}'Được hỗ trợ bởi
Giờ bạn đã sẵn sàng bắt đầu viết macro để thao tác trên bộ dữ liệu này.
Cách viết và sử dụng macro dbt
Bây giờ, hãy thử viết một vài macro của riêng chúng ta.
Định nghĩa macro
Đặt định nghĩa macro trong các tệp .sql dưới thư mục macros/.
Khi đặt tên macro, hãy đảm bảo mỗi macro có tên mô tả được mục đích, và dùng tham số để linh hoạt. Thêm chú thích ngắn ở đầu giúp đồng đội hiểu ý định của nó.
Bạn gọi macro bên trong model với {{ macro_name(arg1, arg2) }}. Chúng có thể được dùng trong mệnh đề SELECT, bộ lọc WHERE, hoặc thậm chí toàn bộ khối CTE, cho phép bạn đưa các mẫu SQL dùng lại vào bất kỳ đâu.
Ví dụ:
-- models/my_model.sqlSELECT
order_id,
{{ cents_to_dollars('amount_in_cents') }} AS amount_in_dollars,
{{ cents_to_dollars('tax_in_cents',precision=4) }} AS tax_in_dollars
FROM {{ ref('raw_orders') }}Được hỗ trợ bởi
Gọi macro từ CLI
Với các tác vụ vận hành ngoài quá trình build model, dùng định dạng/cú pháp sau:
dbt run-operation macro_name --args'{"param": "value"}'Được hỗ trợ bởi
Điều này cho phép bạn thực thi SQL tiện ích như tạo schema hoặc dọn dẹp dữ liệu mà không cần build model.
Ví dụ lệnh:
dbt run-operation greet --args'{"name": "Austin"}'Được hỗ trợ bởi
Sử dụng macro từ package
Macro cũng có thể đến từ các package trong dbt, chẳng hạn như dbt-utils.
Khi bạn cài một package qua packages.yml, macro của package đó sẽ khả dụng ngay. Để làm điều này, bạn cần chạy dbt deps.
Sau đó, bạn có thể gọi các macro vừa thêm theo định dạng: package_name.macro_name.
Tổ chức tệp macro
Để tổ chức tốt hơn, hãy sắp xếp và tách macro theo chức năng để cải thiện khả năng bảo trì.
Cố gắng nhóm các macro liên quan vào các tệp riêng (ví dụ, date_utils.sql, string_utils.sql) để dễ bảo trì. Điều này giúp dễ định vị và cập nhật logic theo thời gian.
Ví dụ macro dbt trong thực tế
Dưới đây là một số ví dụ về macro trong các trường hợp sử dụng thực tiễn hơn:
Macro so sánh ngày
Giả sử bạn muốn tạo một hàm thường dùng để so sánh ngày.
Trong trường hợp này, bạn có thể dùng macro để tính chênh lệch ngày giữa hai trường ngày đồng thời xử lý khác biệt cú pháp SQL.
Bắt đầu bằng cách tạo tệp mới tại: macros/date_utils.sql.
Lợi ích: Trên dev, các model nằm trong môi trường dev_analytics (cô lập). Trên prod, chúng nằm trong analytics. Điều này tạo ra triển khai dự đoán được và tránh xung đột.
Thực thi SQL bên ngoài model
Bạn cũng có thể chạy lệnh SQL ngoài model cho các tác vụ như dọn dẹp bảng hoặc cập nhật metadata mà không cần tạo model.
Bạn có thể viết một macro thực thi SQL thô rồi chạy nó qua dbt run-operation.
Điều này hữu ích cho DDL (drop/tạo bảng) hoặc cập nhật metadata không phù hợp để đưa vào model.
Điều này cho phép bạn chạy macro mà không cần đưa chúng vào trong model.
Ví dụ macro có tham số
Chúng ta cũng có thể tạo một macro được tham số hóa cao, giống như một hàm.
Trong ví dụ này, chúng ta sẽ lọc bản ghi dựa trên một trạng thái cho trước, khi các giá trị được cung cấp. Điều này dùng câu lệnh if và do để tạo logic.
with src as(select*from {{ ref('orders') }}
)select*from src
{{ where_orders(status='shipped', min_date='2025-01-05') }}Được hỗ trợ bởi
Macro này xây dựng sẵn logic khi một đối số bị bỏ qua; tiêu chí đó sẽ bị lờ đi. Điều này giúp phần logic tùy chọn gọn gàng.
Thực tiễn tốt nhất cho macro dbt
Thiết kế macro tốt không chỉ là để SQL biên dịch được. Những macro tốt nhất dễ tìm, được ghi chép đầy đủ, có tính dự đoán, có thể kiểm thử, và dễ ngưng dùng hoặc mở rộng.
Dưới đây là một số thực tiễn nên theo:
1. Quy ước đặt tên và thiết kế tham số
Tương tự SQL và ngôn ngữ lập trình, quy ước đặt tên cần được tuân thủ để đảm bảo dễ đọc.
Một vài mẹo đặt tên:
Rõ ràng và hướng hành động. Ưu tiên động từ hoặc ý định rõ (ví dụ, generate_select_list, where_orders) thay vì tên mơ hồ như helper.
Giữ tên ổn định và viết thường. Dùng snake_case và tiền tố ổn định theo miền, ví dụ date_*, string_*, test_*, admin_*.
2. Chiến lược tài liệu
Bạn nên hình thành thói quen ghi chép những gì mình tạo. Tài liệu nên ở nơi developer thường xem.
Ví dụ, kết hợp chú thích nội tuyến + một macros.yml (hoặc schema.yml) với mô tả và ví dụ.
Nội dung tài liệu có thể gồm:
Mục đích và đầu ra mong đợi (1–2 câu)
Bảng tham số với giá trị mặc định và giá trị cho phép
Ví dụ ngắn về cách gọi trong model và với run-operation
Ghi chú hành vi xuyên cơ sở dữ liệu
Ví dụ đoạn cấu hình:
version:2macros:-name: days_between
description:|
Return day difference between two date expressions, normalized across warehouses.arguments:-name: start_col
type: string
description: Column/expression for the start date
-name: end_col
type: string
description: Column/expression for the end date
docs:show:trueĐược hỗ trợ bởi
3. Tổ chức mã
Mã của bạn cũng cần được tổ chức tốt, đặc biệt khi bạn phải quản lý số lượng lớn macro trong thư mục.
Hãy cấu trúc theo miền để dễ sử dụng. Ví dụ:
macros/date_utils.sql
macros/string_utils.sql
macros/testing/ (test tùy chỉnh)
macros/admin/ (DDL, dọn dẹp)
macros/compat/ (shim cho warehouse)
4. Giữ macro nhỏ và đơn nhiệm
Một macro nên làm tốt một việc. Nếu macro trở nên quá lớn hoặc xử lý logic không liên quan, hãy tách thành macro nhỏ hơn. Điều này cải thiện khả năng tái sử dụng và giúp kiểm thử đơn giản hơn.
5. Kiểm thử macro với dữ liệu tiêu biểu
Dùng các model kiểm thử chuyên dụng hoặc môi trường staging để xác thực hành vi macro.
Ví dụ:
Tạo một seed nhỏ bao quát các trường hợp biên.
Viết một model kiểm thử gọi macro với các tham số khác nhau.
Dùng dbt run và kiểm tra SQL đã biên dịch để đảm bảo đúng đắn.
Mẹo hay: Ghép macro với test tùy chỉnh dbt test để xác minh đầu ra đáp ứng các ràng buộc mong đợi.
Các trường hợp sử dụng và ứng dụng phổ biến
Macro dbt rất linh hoạt, và ứng dụng của chúng mở rộng vào nhiều quy trình công việc hằng ngày của analytics engineering.
Dưới đây là một số ví dụ mở rộng, chi tiết:
Chuẩn hóa các chuyển đổi dữ liệu: Macro có thể đảm bảo cùng quy ước đặt tên, cắt khoảng trắng, xử lý null và ép kiểu được áp dụng cho nhiều model. Chẳng hạn, bạn có thể tạo macro standardize_customer_name để làm sạch và định dạng tên thống nhất trên tất cả data mart.
Hỗ trợ truy vấn xuyên cơ sở dữ liệu: Các warehouse có khác biệt nhỏ về cú pháp SQL. Macro có thể trừu tượng hóa các khác biệt đó—như dùng DATEDIFF trên Snowflake và DATE_DIFF trên BigQuery. Điều này giúp model của bạn có thể di chuyển.
Tự động hóa kiểm tra chất lượng: Viết các macro dùng lại để tạo test dữ liệu, như kiểm tra trùng ID, cột quan trọng bị null, hoặc giá trị vượt phạm vi. Chúng có thể được gọi trong nhiều model kiểm thử.
Đơn giản hóa mẫu SQL lặp lại: Các CTE phổ biến, trường tính toán, hoặc mệnh đề lọc có thể được tham số hóa trong macro. Ví dụ, một macro xây dựng mệnh đề WHERE động dựa trên bộ lọc tùy chọn giúp tránh sao chép-dán logic phức tạp.
Kỹ thuật nâng cao và tối ưu hiệu năng
Macro dbt cũng có thể dùng trong các ứng dụng nâng cao hơn. Hãy xem hai cách phổ biến dưới đây.
Mẫu đệ quy và siêu lập trình
Macro có thể gọi macro khác, lặp qua metadata, hoặc động sinh các đoạn SQL dựa trên việc kiểm tra lược đồ.
Điều này cho phép bạn:
Tự động tạo model staging cho mỗi bảng source.
Tạo truy vấn pivot/unpivot mà không cần gõ thủ công từng cột.
Xây dựng truy vấn nhận biết môi trường bằng cách lặp qua biến cấu hình.
Chiến lược tối ưu hiệu năng
Bạn cũng có thể tối ưu thêm để cải thiện hiệu năng:
Giảm độ phức tạp truy vấn bằng cách chỉ bao gồm có chọn lọc các cột hoặc join cần thiết.
Điều chỉnh materialization hoặc chiến lược SQL dựa trên loại warehouse.
Tích hợp với hệ sinh thái dbt
Macro được tạo ra để là một phần của hệ sinh thái dbt, khiến chúng mạnh mẽ hơn khi kết hợp với các package, tính năng cloud, và công cụ bên ngoài.
Quản lý package
Nhiều package cộng đồng của dbt như dbt-utils, dbt-date, và dbt-expectations về bản chất là tập hợp các macro có khả năng tái sử dụng rất cao.
Các package này mang đến các chuyển đổi, test, và tiện ích dựng sẵn mà không cần phát minh lại bánh xe.
Tương thích với dbt Cloud và công cụ developer
Macro hoạt động liền mạch trong môi trường dbt Cloud, nghĩa là logic SQL động của bạn sẽ hoạt động giống nhau dù chạy cục bộ hay trong job lập lịch trên cloud.
Chúng cũng tích hợp tốt với quản lý phiên bản, pipeline CI/CD, và quy trình review mã, đảm bảo cập nhật macro được kiểm thử và triển khai nhất quán.
Chiến lược triển khai trong thực tế
Chuyển từ script SQL truyền thống sang quy trình làm việc dbt dựa trên macro đòi hỏi cả thay đổi kỹ thuật và sự tiếp nhận về mặt văn hóa.
Di trú và quản lý thay đổi
Khi di trú, hãy bắt đầu bằng cách xác định các mẫu SQL lặp lại trên các model. Tiếp theo, tái cấu trúc chúng thành macro một cách dần dần, xác thực rằng SQL đã biên dịch khớp với logic cũ.
Dùng cờ tính năng (var()) để bật/tắt logic macro mới trong quá trình triển khai, giảm thiểu gián đoạn. Quan trọng nhất, bạn sẽ muốn thông báo cho các bên liên quan về thay đổi để tránh làm hỏng các truy vấn downstream.
Quản trị và chiến lược triển khai
Về quản trị, hãy bắt đầu bằng cách thiết lập quy ước đặt tên rõ ràng, tiêu chuẩn tham số, và yêu cầu tài liệu cho tất cả macro.
Tiếp theo, review thay đổi macro trong pull request giống như cập nhật model, đảm bảo đáp ứng tiêu chuẩn hiệu năng và tương thích.
Trong sản xuất, giám sát log job cho các truy vấn do macro sinh để xác minh chúng chạy như mong đợi. Với dự án nặng macro, thiết lập dashboard quan sát để theo dõi thời gian biên dịch và hiệu năng truy vấn theo loại macro.
Kết luận
Macro dbt là phần quan trọng để tăng năng suất và khả năng bảo trì trong các đội ngũ analytics engineering hiện đại. Sử dụng model dbt cùng với macro có thể mang lại kết quả tốt hơn cho các hoạt động làm sạch dữ liệu.
Làm sao tôi có thể tối ưu hiệu năng cho macro dbt?⌄
Điều quan trọng là đảm bảo SQL mà macro của bạn tạo ra hiệu quả. Tránh dùng vòng lặp để xây dựng SQL từng dòng. Hãy để cơ sở dữ liệu xử lý bằng truy vấn theo tập hợp. Ngoài ra, giữ macro tập trung và tránh thêm quá nhiều lớp logic tạo ra SQL quá phức tạp. Nếu bạn lặp lại cùng một phép tính, hãy cân nhắc cache nó trong macro hoặc chuyển nó vào một model.
Những sai lầm phổ biến khi dùng macro dbt là gì?⌄
Lỗi thường gặp là làm macro quá phức tạp đến mức khó hiểu hoặc khó debug. Một lỗi khác là không cân nhắc sự khác biệt giữa các cơ sở dữ liệu. Đôi khi bạn quên escape biến, có thể gây lỗi hoặc tạo SQL khó đọc cho đồng đội.
Tôi debug vấn đề với macro dbt như thế nào?⌄
Bắt đầu bằng cách xem SQL đã biên dịch trong thư mục target/compiled. Tệp này cho bạn thấy chính xác macro đã tạo ra gì. Bạn cũng có thể thêm câu lệnh {{ log('message', info=True) }} vào macro để xem chuyện gì xảy ra lúc chạy. Nếu có lỗi, hãy đơn giản hóa đầu vào và kiểm thử với ví dụ nhỏ hơn bằng dbt run-operation cho đến khi tìm ra vấn đề.
Macro dbt có thể dùng với công cụ hay framework khác không?⌄
Có, nhưng chỉ thông qua chính dbt. Ví dụ, các công cụ như Airflow hoặc Dagster có thể chạy các lệnh dbt gọi macro của bạn. Trong dbt, macro cũng có thể được chia sẻ qua các package như dbt-utils. Tuy nhiên, bạn không thể chạy trực tiếp một macro dbt trong công cụ khác trừ khi bạn bọc nó trong một lệnh dbt.
Thực tiễn tốt nhất để viết tài liệu cho macro dbt là gì?⌄
Một số thực tiễn tốt là hãy nghĩ về macro như các hàm nhỏ cho người khác dùng. Hãy cân nhắc viết mô tả rõ ràng về những gì chúng làm, liệt kê tất cả đối số (kèm mặc định nếu có), và đưa ví dụ ngắn cách sử dụng. Nếu macro hoạt động khác nhau trên các cơ sở dữ liệu, cũng nên ghi chú. Tài liệu tốt giúp đồng đội dễ tin tưởng và tái sử dụng công việc của bạn.
Tôi là Austin, một blogger và cây bút công nghệ với nhiều năm kinh nghiệm làm nhà khoa học dữ liệu và nhà phân tích dữ liệu trong lĩnh vực chăm sóc sức khỏe. Khởi đầu hành trình công nghệ với nền tảng sinh học, tôi hiện hỗ trợ những người khác thực hiện chuyển đổi tương tự thông qua blog công nghệ của mình. Niềm đam mê công nghệ đã đưa tôi đến với việc cộng tác viết cho hàng chục công ty SaaS, truyền cảm hứng cho người khác và chia sẻ trải nghiệm của bản thân.
Xây dựng các đường ống dữ liệu đáng tin cậy và có khả năng mở rộng với dbt Fundamentals, một khóa học thực hành được thiết kế dành cho các nhà phân tích dữ liệu, kỹ sư dữ liệu và kỹ sư phân tích.
Trong kỹ thuật phân tích (analytics engineering), dbt (data build tool) macro cung cấp một cách mạnh mẽ để viết logic SQL động, có thể tái sử dụng thông qua các khối mã dùng chung.
Trong hướng dẫn này, chúng ta sẽ khám phá các khái niệm cơ bản về macro dbt, cách xây dựng chúng bằng Jinja, thực tiễn tốt để dễ bảo trì, và các ứng dụng thực tế, kèm theo ví dụ mã.
Macro dbt là gì?
Macro dbt là các khối mã có thể tái sử dụng được viết bằng ngôn ngữ mẫu Jinja trong dbt, cho phép bạn tạo ra SQL một cách động. Chúng giúp giảm lặp lại và tập trung hóa logic chuyển đổi.
Các macro hoạt động tương tự như hàm trong các ngôn ngữ lập trình truyền thống.
Ví dụ, nếu bạn cần tính một chỉ số cụ thể trên nhiều model, một macro có thể đóng gói phép tính đó, giúp dễ dàng bảo trì và cập nhật hơn.
Macro cũng có thể được lưu trong các package, chẳng hạn như dbt-utils.
Tại sao dùng macro dbt?
Macro mang lại nhiều lợi thế, chủ yếu là:
Những lợi ích này dẫn tới codebase gọn gàng, dễ bảo trì và có khả năng mở rộng hơn.
Các khái niệm nền tảng về macro dbt
Để giúp bạn hiểu cách macro hoạt động trong dbt, hãy cùng xem một số khái niệm chính.
1. Tính có thể tái sử dụng
Macro cho phép bạn định nghĩa một phần logic SQL một lần và dùng lại trên nhiều model, test, hoặc thậm chí macro khác.
2. Bộ máy mẫu Jinja
Jinja tích hợp với dbt giúp chèn biến, áp dụng điều kiện, và lặp qua danh sách, tất cả diễn ra trước khi SQL của bạn đến cơ sở dữ liệu. dbt biên dịch mẫu này thành SQL thô, khiến macro không phụ thuộc vào hệ cơ sở dữ liệu.
3. Giới thiệu kỹ thuật lập trình
Macro có thể biến SQL thành một khung có thể lập trình. Chúng cho phép logic, vòng lặp và điều kiện—những thứ mà SQL chuẩn không xử lý linh hoạt bằng.
Tương tự hàm, macro trong dbt có thể nhận đối số (tham số) và có thể được gọi với các đầu vào khác nhau để tạo ra đầu ra khác nhau. Chúng giúp đơn giản hóa các chuyển đổi phức tạp bằng cách chia nhỏ thành các đơn vị nhỏ, có thể tái sử dụng.
Xây dựng macro với Jinja
Tiếp theo, hãy xem cách tự xây dựng một số macro.
Jinja là bộ máy mẫu vận hành macro dbt, cho phép bạn xử lý SQL như văn bản động, có thể lập trình.
Cấu trúc mẫu và dấu phân cách
Để dùng Jinja, bạn sẽ cần các cấu trúc mẫu và dấu phân cách cụ thể.
Dưới đây là một số cấu trúc và dấu phân cách thường dùng:
{{ }}: Chèn biểu thức.{% %}: Thực thi câu lệnh.{# #}: Thêm chú thích để dbt bỏ qua.Trong macro,
{{ ... }}dùng cho biểu thức cần xuất ra giá trị (ví dụ: tên cột hoặc phép tính), trong khi{% ... %}dùng cho điều khiển luồng (vòng lặp, if/else, định nghĩa macro). Chú thích Jinja dùng{# ... #}và bị loại bỏ hoàn toàn khi biên dịch.Đây là ví dụ về cú pháp dùng cho các câu lệnh trong macro:
Đây là ví dụ cách dùng câu lệnh để tạo một macro:
Để chạy macro, dùng lệnh này:
Quản lý biến
Bạn có thể truyền biến vào macro hoặc định nghĩa bên trong. Các bộ lọc như
upperhoặclowercó thể chuyển đổi giá trị văn bản.Dưới đây là cách triển khai hàm
upperđể chuyển toàn bộ giá trị văn bản thành chữ in hoa.Để áp dụng, bạn sẽ cần gọi/tham chiếu macro vừa tạo trong model dbt của mình.
Ví dụ mã:
Cấu trúc điều khiển
Tương tự các ngôn ngữ lập trình, macro dbt có thể cung cấp các cấu trúc sau:
{% if %}/{% endif %}):{% for %}/{% endfor %})Các cấu trúc này cho phép bạn xây dựng động các mệnh đề SQL hoặc tạo nhiều biểu thức dựa trên đầu vào.
Điều này giúp macro xử lý các tác vụ sinh SQL phức tạp dễ dàng hơn.
Xử lý tham số và quản lý lỗi
Macro có thể xác thực đầu vào và phát sinh lỗi khi biên dịch để tránh sự cố lúc chạy.
Tham số được định nghĩa trong khai báo macro bằng dấu ngoặc
(), tương tự định nghĩa hàm trong ngôn ngữ lập trình.Ví dụ cách chúng ta bao gồm 2 tham số:
Như bạn thấy, ở dòng đầu, chúng ta đã bao gồm cả
param1vàparam2.Để gọi macro trong một model dbt, bạn nên dùng cặp ngoặc nhọn kép {{ }}. Các tham số được truyền như đối số trong dấu ngoặc đơn.
Trong trường hợp này, chúng ta chỉ định cả
column_avàcolumn_blàm tham số.Hướng dẫn thiết lập để làm việc với macro dbt
Trước khi bắt đầu xây dựng và sử dụng macro, hãy thiết lập môi trường làm việc để bạn có thể theo dõi các ví dụ trong hướng dẫn này.
Điều này đảm bảo bạn đã cài đặt dbt, nạp một bộ dữ liệu mẫu, và có cấu trúc thư mục phù hợp để tạo macro.
1. Cài đặt dbt Core
Bạn cần cài dbt Core cục bộ. Nếu dùng Postgres trong hướng dẫn này, cài bằng lệnh:
Nếu dự án của bạn dùng data warehouse, chạy các lệnh tương ứng:
2. Tạo một dự án dbt
Trước khi chạy bất kỳ lệnh dbt nào, chúng ta cần thiết lập môi trường dự án.
Đi đến thư mục dự án mong muốn của bạn.
Đây là nơi bạn lưu trữ các tệp dự án dbt. Trong trường hợp này, chúng ta sẽ lưu tất cả các tệp liên quan trong thư mục dự án dbt này.
Để khởi tạo một dự án dbt, bạn cần chạy:
Tạo cấu trúc thư mục theo định dạng sau:
3. Chuẩn bị bộ dữ liệu mẫu
Chúng ta sẽ dùng Python để tạo một bộ dữ liệu orders nhỏ và nạp vào Postgres (hoặc warehouse bạn chọn).
Lưu ý: Cập nhật chuỗi kết nối cho cơ sở dữ liệu của bạn.
4. Tạo source trong dbt
Thêm nội dung sau vào
models/src_orders.yml:5. Kiểm tra kết nối và source
Giờ bạn đã sẵn sàng bắt đầu viết macro để thao tác trên bộ dữ liệu này.
Cách viết và sử dụng macro dbt
Bây giờ, hãy thử viết một vài macro của riêng chúng ta.
Định nghĩa macro
Đặt định nghĩa macro trong các tệp .sql dưới thư mục macros/.
Khi đặt tên macro, hãy đảm bảo mỗi macro có tên mô tả được mục đích, và dùng tham số để linh hoạt. Thêm chú thích ngắn ở đầu giúp đồng đội hiểu ý định của nó.
Ví dụ:
Gọi macro trong model
Bạn gọi macro bên trong model với {{ macro_name(arg1, arg2) }}. Chúng có thể được dùng trong mệnh đề SELECT, bộ lọc WHERE, hoặc thậm chí toàn bộ khối CTE, cho phép bạn đưa các mẫu SQL dùng lại vào bất kỳ đâu.
Ví dụ:
Gọi macro từ CLI
Với các tác vụ vận hành ngoài quá trình build model, dùng định dạng/cú pháp sau:
Điều này cho phép bạn thực thi SQL tiện ích như tạo schema hoặc dọn dẹp dữ liệu mà không cần build model.
Ví dụ lệnh:
Sử dụng macro từ package
Macro cũng có thể đến từ các package trong dbt, chẳng hạn như dbt-utils.
Khi bạn cài một package qua
packages.yml, macro của package đó sẽ khả dụng ngay. Để làm điều này, bạn cần chạydbt deps.Sau đó, bạn có thể gọi các macro vừa thêm theo định dạng:
package_name.macro_name.Tổ chức tệp macro
Để tổ chức tốt hơn, hãy sắp xếp và tách macro theo chức năng để cải thiện khả năng bảo trì.
Cố gắng nhóm các macro liên quan vào các tệp riêng (ví dụ, date_utils.sql, string_utils.sql) để dễ bảo trì. Điều này giúp dễ định vị và cập nhật logic theo thời gian.
Ví dụ macro dbt trong thực tế
Dưới đây là một số ví dụ về macro trong các trường hợp sử dụng thực tiễn hơn:
Macro so sánh ngày
Giả sử bạn muốn tạo một hàm thường dùng để so sánh ngày.
Trong trường hợp này, bạn có thể dùng macro để tính chênh lệch ngày giữa hai trường ngày đồng thời xử lý khác biệt cú pháp SQL.
Bắt đầu bằng cách tạo tệp mới tại:
macros/date_utils.sql.Tiếp theo, dùng đoạn mã sau:
Giờ chúng ta sẽ dùng macro
days_betweenmới này trong một model.Tùy biến macro
generate_schema_nameTheo mặc định, dbt dùng một macro mặc định gọi là
generate_schema_name. Macro này dùng để chỉ định tên schema mà một model sẽ được build trong đó.Bạn cũng có thể ghi đè mặc định của dbt để kiểm soát schema dùng theo từng môi trường.
Bạn có thể thêm tệp này tại vị trí:
macros/generate_schema_name.sql.Lợi ích: Trên
dev, các model nằm trong môi trườngdev_analytics(cô lập). Trênprod, chúng nằm tronganalytics. Điều này tạo ra triển khai dự đoán được và tránh xung đột.Thực thi SQL bên ngoài model
Bạn cũng có thể chạy lệnh SQL ngoài model cho các tác vụ như dọn dẹp bảng hoặc cập nhật metadata mà không cần tạo model.
Bạn có thể viết một macro thực thi SQL thô rồi chạy nó qua
dbt run-operation.Điều này hữu ích cho DDL (drop/tạo bảng) hoặc cập nhật metadata không phù hợp để đưa vào model.
Đây là macro:
Tiếp theo, chạy thao tác này trong terminal:
Điều này cho phép bạn chạy macro mà không cần đưa chúng vào trong model.
Ví dụ macro có tham số
Chúng ta cũng có thể tạo một macro được tham số hóa cao, giống như một hàm.
Trong ví dụ này, chúng ta sẽ lọc bản ghi dựa trên một trạng thái cho trước, khi các giá trị được cung cấp. Điều này dùng câu lệnh
ifvàdođể tạo logic.Giờ áp dụng macro này trong một model:
Macro này xây dựng sẵn logic khi một đối số bị bỏ qua; tiêu chí đó sẽ bị lờ đi. Điều này giúp phần logic tùy chọn gọn gàng.
Thực tiễn tốt nhất cho macro dbt
Thiết kế macro tốt không chỉ là để SQL biên dịch được. Những macro tốt nhất dễ tìm, được ghi chép đầy đủ, có tính dự đoán, có thể kiểm thử, và dễ ngưng dùng hoặc mở rộng.
Dưới đây là một số thực tiễn nên theo:
1. Quy ước đặt tên và thiết kế tham số
Tương tự SQL và ngôn ngữ lập trình, quy ước đặt tên cần được tuân thủ để đảm bảo dễ đọc.
Một vài mẹo đặt tên:
generate_select_list,where_orders) thay vì tên mơ hồ nhưhelper.date_*,string_*,test_*,admin_*.2. Chiến lược tài liệu
Bạn nên hình thành thói quen ghi chép những gì mình tạo. Tài liệu nên ở nơi developer thường xem.
Ví dụ, kết hợp chú thích nội tuyến + một
macros.yml(hoặcschema.yml) với mô tả và ví dụ.Nội dung tài liệu có thể gồm:
run-operationVí dụ đoạn cấu hình:
3. Tổ chức mã
Mã của bạn cũng cần được tổ chức tốt, đặc biệt khi bạn phải quản lý số lượng lớn macro trong thư mục.
Hãy cấu trúc theo miền để dễ sử dụng. Ví dụ:
macros/date_utils.sqlmacros/string_utils.sqlmacros/testing/(test tùy chỉnh)macros/admin/(DDL, dọn dẹp)macros/compat/(shim cho warehouse)4. Giữ macro nhỏ và đơn nhiệm
Một macro nên làm tốt một việc. Nếu macro trở nên quá lớn hoặc xử lý logic không liên quan, hãy tách thành macro nhỏ hơn. Điều này cải thiện khả năng tái sử dụng và giúp kiểm thử đơn giản hơn.
5. Kiểm thử macro với dữ liệu tiêu biểu
Dùng các model kiểm thử chuyên dụng hoặc môi trường staging để xác thực hành vi macro.
Ví dụ:
dbt runvà kiểm tra SQL đã biên dịch để đảm bảo đúng đắn.Mẹo hay: Ghép macro với test tùy chỉnh
dbt testđể xác minh đầu ra đáp ứng các ràng buộc mong đợi.Các trường hợp sử dụng và ứng dụng phổ biến
Macro dbt rất linh hoạt, và ứng dụng của chúng mở rộng vào nhiều quy trình công việc hằng ngày của analytics engineering.
Dưới đây là một số ví dụ mở rộng, chi tiết:
standardize_customer_nameđể làm sạch và định dạng tên thống nhất trên tất cả data mart.DATEDIFFtrên Snowflake vàDATE_DIFFtrên BigQuery. Điều này giúp model của bạn có thể di chuyển.WHEREđộng dựa trên bộ lọc tùy chọn giúp tránh sao chép-dán logic phức tạp.Kỹ thuật nâng cao và tối ưu hiệu năng
Macro dbt cũng có thể dùng trong các ứng dụng nâng cao hơn. Hãy xem hai cách phổ biến dưới đây.
Mẫu đệ quy và siêu lập trình
Macro có thể gọi macro khác, lặp qua metadata, hoặc động sinh các đoạn SQL dựa trên việc kiểm tra lược đồ.
Điều này cho phép bạn:
Chiến lược tối ưu hiệu năng
Bạn cũng có thể tối ưu thêm để cải thiện hiệu năng:
Tích hợp với hệ sinh thái dbt
Macro được tạo ra để là một phần của hệ sinh thái dbt, khiến chúng mạnh mẽ hơn khi kết hợp với các package, tính năng cloud, và công cụ bên ngoài.
Quản lý package
Nhiều package cộng đồng của dbt như
dbt-utils,dbt-date, vàdbt-expectationsvề bản chất là tập hợp các macro có khả năng tái sử dụng rất cao.Các package này mang đến các chuyển đổi, test, và tiện ích dựng sẵn mà không cần phát minh lại bánh xe.
Tương thích với dbt Cloud và công cụ developer
Macro hoạt động liền mạch trong môi trường dbt Cloud, nghĩa là logic SQL động của bạn sẽ hoạt động giống nhau dù chạy cục bộ hay trong job lập lịch trên cloud.
Chúng cũng tích hợp tốt với quản lý phiên bản, pipeline CI/CD, và quy trình review mã, đảm bảo cập nhật macro được kiểm thử và triển khai nhất quán.
Chiến lược triển khai trong thực tế
Chuyển từ script SQL truyền thống sang quy trình làm việc dbt dựa trên macro đòi hỏi cả thay đổi kỹ thuật và sự tiếp nhận về mặt văn hóa.
Di trú và quản lý thay đổi
Khi di trú, hãy bắt đầu bằng cách xác định các mẫu SQL lặp lại trên các model. Tiếp theo, tái cấu trúc chúng thành macro một cách dần dần, xác thực rằng SQL đã biên dịch khớp với logic cũ.
Dùng cờ tính năng (
var()) để bật/tắt logic macro mới trong quá trình triển khai, giảm thiểu gián đoạn. Quan trọng nhất, bạn sẽ muốn thông báo cho các bên liên quan về thay đổi để tránh làm hỏng các truy vấn downstream.Quản trị và chiến lược triển khai
Về quản trị, hãy bắt đầu bằng cách thiết lập quy ước đặt tên rõ ràng, tiêu chuẩn tham số, và yêu cầu tài liệu cho tất cả macro.
Tiếp theo, review thay đổi macro trong pull request giống như cập nhật model, đảm bảo đáp ứng tiêu chuẩn hiệu năng và tương thích.
Trong sản xuất, giám sát log job cho các truy vấn do macro sinh để xác minh chúng chạy như mong đợi. Với dự án nặng macro, thiết lập dashboard quan sát để theo dõi thời gian biên dịch và hiệu năng truy vấn theo loại macro.
Kết luận
Macro dbt là phần quan trọng để tăng năng suất và khả năng bảo trì trong các đội ngũ analytics engineering hiện đại. Sử dụng model dbt cùng với macro có thể mang lại kết quả tốt hơn cho các hoạt động làm sạch dữ liệu.
Muốn tìm hiểu thêm về dbt? Khóa học Introduction to dbt và dbt Tutorial của chúng tôi có thể hữu ích cho bạn.