DataOps 7 — Tài liệu, Catalog & chia sẻ tri thức
"Bảng này nghĩa là gì, số này tính sao?"
Trong đội dữ liệu ngân hàng, câu hỏi lặp đi lặp lại nhiều nhất không phải là "pipeline chạy chưa" mà là: "Bảng mart_du_no_khach_hang này lấy từ đâu?", "Cột du_no_qua_han tính ra sao?", "Chỉ tiêu 'tỷ lệ nợ xấu' trong báo cáo tháng khác gì với dashboard rủi ro?". Người trả lời luôn là một hai anh chị "biết tuốt" — và mỗi lần họ nghỉ phép hoặc chuyển team, cả đội đứng hình.
Đó là tri thức trong đầu (tribal knowledge): hiểu biết về dữ liệu nằm rải rác trong trí nhớ vài cá nhân, không được ghi lại. Hệ quả: onboarding người mới mất hàng tháng, mọi câu hỏi đều phải hỏi người, và độ tin cậy vào số liệu thấp vì không ai truy được nguồn gốc.
Bài này thuộc series DataOps. Sau khi đã có Git & analytics as code, testing, CI/CD và observability, mảnh ghép cuối để đội scale là tài liệu & khám phá dữ liệu: biến tri thức ẩn thành tài sản chung, tra cứu được, luôn cập nhật.
Vì sao tài liệu dữ liệu đặc biệt quan trọng
- Onboarding nhanh: người mới tự đọc data dictionary thay vì hỏi từng bảng.
- Tự phục vụ (self-service): analyst/cán bộ nghiệp vụ tự tìm bảng, hiểu cột, tự viết truy vấn — không phải mở ticket chờ data engineer.
- Giảm phụ thuộc cá nhân: tri thức thuộc về tổ chức, không "chết" theo người nghỉ việc.
- Tin cậy & tuân thủ: khi mỗi chỉ tiêu có định nghĩa, nguồn, cách tính rõ ràng, số liệu báo cáo mới đứng vững trước kiểm toán và thanh tra.
Điểm mấu chốt: tài liệu tốt trả lời được đúng hai câu "nghĩa là gì" (ngữ nghĩa) và "tính thế nào" (công thức, nguồn).
Docs-as-code: tài liệu sống cùng code
Vấn đề kinh điển của tài liệu là lệch pha (drift): code sửa mà tài liệu (thường nằm trong Word/Confluence riêng) không ai update, nên sau vài tháng tài liệu sai nhiều hơn đúng, và không ai còn tin nó nữa.
Docs-as-code giải quyết bằng cách đặt tài liệu ngay trong repo cùng code, viết bằng định dạng văn bản (Markdown/YAML), và cập nhật trong cùng một Pull Request với thay đổi code:
- Sửa logic một model → PR bắt buộc kèm sửa
descriptioncủa model/cột. - Reviewer thấy diff cả code lẫn docs cùng lúc, dễ bắt lỗi lệch.
- Tài liệu được version, review, CI kiểm tra như mọi code khác.
Với dbt, docs-as-code phát huy tối đa: bạn khai báo mô tả ngay cạnh model, và dbt docs generate tự sinh trang tài liệu + data dictionary + biểu đồ lineage từ chính metadata đó — không phải viết tay lần hai.
# models/marts/finance/mart_du_no_khach_hang.yml — docs sống cùng model
version: 2
models:
- name: mart_du_no_khach_hang
description: >
Dư nợ tín dụng theo khách hàng, cập nhật cuối ngày (T+1).
Nguồn: hệ thống core LOS, đã loại tài khoản đóng.
Owner: team Data Rủi ro. SLA: sẵn sàng trước 08:00 mỗi ngày.
meta:
owner: "risk-data@ncb"
sla: "08:00 daily"
pii: false
columns:
- name: customer_id
description: "Mã khách hàng, khoá tới dim_customer."
tests: [not_null, unique]
- name: du_no_qua_han
description: >
Dư nợ quá hạn = tổng dư nợ các khế ước có số ngày quá hạn > 0.
Không bao gồm lãi treo. Đơn vị: VND.
- name: nhom_no
description: >
Nhóm nợ theo Thông tư 11/2021: 1 (đủ tiêu chuẩn) đến 5 (có khả năng mất vốn).
tests:
- accepted_values: {values: [1, 2, 3, 4, 5]}
Đoạn YAML trên là minh hoạ khai báo dbt — nó vừa cấu hình test, vừa là nội dung tài liệu. Khi ai đó đọc trang docs sinh ra, họ thấy ngay du_no_qua_han tính thế nào, nhom_no theo chuẩn nào, ai là owner.
Data Catalog: tìm & khám phá dữ liệu
Docs-as-code giải quyết nội dung, nhưng khi warehouse có hàng trăm bảng, vấn đề tiếp theo là tìm được đúng bảng và hiểu ngữ cảnh của nó. Đó là việc của data catalog — một cổng khám phá dữ liệu toàn tổ chức (chi tiết ở Catalog & Lineage).
Một catalog tốt cung cấp:
| Tính năng | Trả lời câu hỏi |
|---|---|
| Search | "Có bảng nào về dư nợ khách hàng cá nhân?" |
| Metadata | Schema, kiểu dữ liệu, số dòng, lần cập nhật gần nhất |
| Business glossary | "Nợ xấu" chính thức nghĩa là gì trong ngân hàng |
| Lineage | Cột này chảy từ bảng nguồn nào qua model nào |
| Popularity | Bảng nào được truy vấn nhiều → đáng tin cậy hơn |
| Owner & liên hệ | Ai chịu trách nhiệm, hỏi ai khi nghi ngờ |
Catalog biến kho dữ liệu từ "mê cung chỉ người quen mới đi được" thành siêu thị tự phục vụ: người dùng gõ từ khoá, thấy bảng, đọc mô tả, xem lineage để tin, rồi copy ví dụ truy vấn. Lineage đặc biệt quan trọng ở ngân hàng: khi thanh tra hỏi "con số nợ xấu trong báo cáo NHNN truy từ đâu", catalog cho phép lần ngược từ ô báo cáo về tận bảng nguồn core.
Tài liệu gì? — danh mục tối thiểu
Không phải mọi thứ đều cần tài liệu bằng nhau. Với mỗi data product (bảng mart, dataset công bố), tối thiểu ghi:
- Định nghĩa bảng & cột: mỗi bảng, mỗi cột nghĩa là gì (data dictionary).
- Nguồn & cách tính chỉ tiêu (semantic): chỉ tiêu này lấy từ bảng/cột nào, công thức ra sao — đây là phần hay bị bỏ sót nhất và gây tranh cãi số liệu nhiều nhất.
- Giả định & lưu ý: ví dụ "loại trừ tài khoản nội bộ", "số liệu T+1 nên hôm nay chưa có ngày hôm nay", "trước 2023 dùng chuẩn phân loại nợ cũ".
- SLA: dữ liệu sẵn sàng lúc mấy giờ, độ trễ bao nhiêu.
- Owner: team/người chịu trách nhiệm và cách liên hệ.
- Ví dụ truy vấn: một hai câu SQL mẫu để người dùng bắt đầu ngay.
Phần ví dụ truy vấn rất đáng đầu tư — nó biến tài liệu tĩnh thành công cụ dùng được. Ví dụ, tài liệu bảng accounts có thể kèm một truy vấn tổng hợp dư nợ theo loại tiền:
-- ▶ Chạy được
SELECT
a.currency,
COUNT(DISTINCT a.customer_id) AS so_khach_hang,
COUNT(*) AS so_tai_khoan,
SUM(a.balance) AS tong_so_du
FROM accounts a
JOIN customers c ON c.id = a.customer_id
GROUP BY a.currency
ORDER BY tong_so_du DESC;
Người dùng đọc tài liệu, chạy thử ví dụ, thấy ngay hình dạng dữ liệu — nhanh hơn nhiều so với hỏi người.
Business glossary: một định nghĩa cho một chỉ tiêu
Nguồn gốc lớn nhất của tranh cãi số liệu ở ngân hàng là cùng một tên gọi, nhiều định nghĩa. "Khách hàng active" với team Marketing (có giao dịch trong 30 ngày) khác với team Rủi ro (còn dư nợ). "Doanh thu" có tính phí hoàn không?
Business glossary là từ điển thuật ngữ nghiệp vụ được thống nhất toàn tổ chức: mỗi thuật ngữ có một định nghĩa chính thức, một owner nghiệp vụ, và liên kết tới cột/model triển khai nó. Đây là mặt "con người/nghiệp vụ" của cùng một câu chuyện với semantic layer / metric layer (lớp định nghĩa chỉ tiêu tập trung): glossary nói nghĩa là gì, semantic layer thực thi công thức đó một chỗ để mọi dashboard tính giống nhau. Ghép hai thứ lại thì "tỷ lệ nợ xấu" chỉ có đúng một con số, dù xem ở báo cáo hay dashboard nào.
Runbook, ADR và các loại tài liệu khác
Tài liệu dữ liệu không chỉ là mô tả bảng. Một đội trưởng thành duy trì nhiều thể loại, mỗi loại phục vụ một mục đích:
- Runbook / tài liệu vận hành: "khi pipeline X fail thì làm gì". Đã bàn kỹ ở observability & incident — runbook là tài liệu cứu bạn lúc 2 giờ sáng.
- ADR (Architecture Decision Record): ghi lại các quyết định kiến trúc quan trọng và lý do — "vì sao chọn dbt thay vì stored procedure", "vì sao partition theo ngày giao dịch chứ không phải ngày hạch toán". Mỗi ADR là một file Markdown ngắn: bối cảnh, quyết định, hệ quả. Vài tháng sau khi ai đó hỏi "sao lại làm thế này", ADR trả lời thay cho trí nhớ.
- README chuẩn cho mỗi repo/dự án: mở đầu là chạy sao, cấu trúc thư mục, ai owner.
- Knowledge base nội bộ / wiki: nơi đặt hướng dẫn, best practice, câu hỏi thường gặp — chính là ứng dụng bạn đang đọc.
Sơ đồ dưới đây tóm tắt hệ sinh thái: metadata và mô tả sống trong repo (docs-as-code), được tổng hợp lên catalog & glossary, phục vụ nhiều nhóm người dùng khác nhau.
Chống tài liệu lỗi thời
Tài liệu sai còn nguy hiểm hơn không có tài liệu, vì nó tạo lòng tin giả. Bốn cơ chế giữ tài liệu luôn đúng:
- Docs-as-code: tài liệu ở cùng repo, sửa cùng PR — không có "chỗ khác" để quên update.
- Tự động sinh: những gì máy suy ra được (schema, kiểu, lineage, danh sách cột) thì để
dbt docs generate/ catalog tự quét, đừng chép tay. - Đưa vào Definition of Done: một task chỉ "xong" khi tài liệu đã cập nhật. Reviewer từ chối PR sửa logic mà không sửa mô tả.
- Kiểm tra tự động trong CI: ví dụ CI fail nếu một model mới không có
description, hoặc cột PII chưa gắn tag. Có thể dùngdbtpackage nhưdbt-meta-testingđể bắt buộc coverage.
Đo độ phủ tài liệu
Cái gì đo được thì cải thiện được. Vài chỉ số đơn giản, hiển thị trên dashboard đội:
| Chỉ số | Ý nghĩa | Mục tiêu |
|---|---|---|
% model có description | Bảng nào chưa được giải thích | 100% cho lớp mart |
% cột (mart) có description | Độ chi tiết data dictionary | > 90% |
% model có owner | Có ai chịu trách nhiệm chưa | 100% |
| % chỉ tiêu báo cáo có trong glossary | Định nghĩa nghiệp vụ đã chuẩn hoá | 100% cho báo cáo NHNN |
| Tuổi tài liệu (ngày từ lần sửa cuối) | Bắt tài liệu "chết" | Cảnh báo nếu > 180 ngày mà model vẫn đổi |
Bắt đầu bằng lớp mart / data product (thứ người ngoài đội dùng) trước, rồi mới tới lớp trung gian.
Văn hoá chia sẻ tri thức
Công cụ chỉ là một nửa; nửa còn lại là văn hoá. Vài thực hành rẻ mà hiệu quả:
- Pairing: hai người cùng làm một model khó → tri thức được truyền ngay, không chờ tài liệu.
- Code review: mỗi PR là một buổi dạy học ngầm; reviewer học cách người khác giải quyết vấn đề.
- Brown-bag / tech talk: buổi chia sẻ ngắn giờ ăn trưa, một người trình bày một chủ đề (VD "cách chúng ta phân loại nợ trong dbt").
- Coi tài liệu là công dân hạng nhất: khen thưởng người viết tài liệu tốt như khen người viết code tốt.
Xem thêm cách vận hành đội ở team practice.
Use case thực tế
Bối cảnh: Team Data NCB có 3 data engineer, 5 analyst nghiệp vụ. Warehouse ~280 bảng dbt. Mỗi tuần, đội nhận trung bình 35 câu hỏi Slack dạng "bảng X là gì / chỉ tiêu Y tính sao", chiếm ~20% thời gian của 2 người có thâm niên. Onboarding một analyst mới mất 6 tuần mới tự viết được truy vấn dư nợ đúng. Tệ hơn, ba team (Marketing, Rủi ro, Kế toán) báo cáo ba con số "khách hàng active" khác nhau lên ban lãnh đạo.
Việc đã làm (theo bài này):
- Docs-as-code: áp policy DoD — mọi PR sửa model lớp mart phải có
descriptioncho model và mọi cột. CI thêm bước fail nếu model mart thiếudescriptionhoặcowner. - Tự sinh & catalog: dựng
dbt docschạy trong CD, đẩy site lên nội bộ; kết nối một data catalog quét metadata + lineage hằng ngày. - Business glossary: ban Dữ liệu chủ trì thống nhất 12 chỉ tiêu cốt lõi (nợ xấu, khách hàng active, dư nợ bình quân...), mỗi chỉ tiêu một định nghĩa + link tới model triển khai qua semantic layer.
- ADR + runbook: ghi lại 8 quyết định kiến trúc lớn; chuyển các hướng dẫn xử lý sự cố rải rác vào runbook trong repo.
Kết quả sau 3 tháng:
- Câu hỏi Slack lặp lại giảm từ 35 xuống ~9/tuần (phần lớn còn lại là ca thật sự mới).
- Thời gian onboarding analyst mới: 6 tuần → 2.5 tuần.
- Ba team nay dùng cùng một định nghĩa "khách hàng active"; báo cáo lãnh đạo hết vênh số.
- Khi thanh tra hỏi nguồn của một dòng báo cáo, đội truy lineage trong vài phút thay vì lục email cả buổi.
- Độ phủ
descriptionlớp mart: từ 41% lên 100%;owner: 100%.
Ghi nhớ
- Tài liệu dữ liệu chống tri thức trong đầu vài người và câu hỏi lặp lại — mục tiêu là trả lời được "bảng này nghĩa là gì" và "số này tính sao".
- Docs-as-code: đặt tài liệu cùng repo, cập nhật cùng PR; những gì máy suy được (schema, lineage) thì tự sinh (dbt docs), đừng chép tay.
- Data catalog biến kho dữ liệu thành siêu thị tự phục vụ: search, metadata, glossary, lineage, popularity, owner — xem Catalog & Lineage.
- Với mỗi data product, ghi tối thiểu: định nghĩa bảng/cột, nguồn & cách tính chỉ tiêu (semantic), giả định, SLA, owner, ví dụ truy vấn.
- Business glossary + semantic layer: một chỉ tiêu, một định nghĩa, một con số — nền tảng cho tự phục vụ và tuân thủ.
- Đừng quên runbook (vận hành), ADR (ghi quyết định & lý do), README chuẩn, wiki nội bộ.
- Chống lỗi thời bằng docs-as-code + tự động + coi tài liệu là một phần Definition of Done + kiểm tra trong CI; và đo độ phủ tài liệu để cải thiện.
- Bối cảnh ngân hàng: định nghĩa chỉ tiêu báo cáo chuẩn hoá & truy vết được là điều kiện cho tuân thủ và cho phép nghiệp vụ tự phục vụ.
Bài viết liên quan
CSV/JSON/Parquet/Avro, lưu trữ theo hàng vs cột, nén, và OLTP vs OLAP.
Data Engineering là gì, vai trò trong vòng đời dữ liệu, và bức tranh hệ sinh thái công cụ.
Vì sao xử lý phân tán, mô hình Spark (RDD/DataFrame), lazy evaluation, shuffle và tối ưu.
Đảm bảo chất lượng & minh bạch dữ liệu bằng dbt: data tests dựng sẵn (unique, not_null, relationships, accepted_values), singular test, unit test, và tài liệu tự sinh kèm lineage graph.