Modeling nâng cao 6 — Semantic Layer & Metrics Layer
Mô hình tinh thần: một định nghĩa, dùng khắp nơi
Hãy tưởng tượng ban giám đốc hỏi một câu tưởng như đơn giản: "Doanh thu tháng trước là bao nhiêu?" Phòng tài chính mở Power BI trả lời một con số. Phòng kinh doanh mở Looker trả lời con số khác. Một analyst chạy SQL ad-hoc trong notebook ra con số thứ ba. Không ai sai — họ chỉ định nghĩa "doanh thu" khác nhau: người trừ hoàn tiền, người không; người tính theo ngày đặt hàng, người theo ngày ghi nhận; người gồm thuế, người bỏ thuế. Kết quả là một cuộc họp cãi nhau "số của ai đúng" thay vì bàn về quyết định kinh doanh.
Gốc rễ vấn đề: logic của metric bị nhân bản ở mọi công cụ tiêu thụ dữ liệu. Mỗi dashboard, mỗi report, mỗi query lặp lại — và trôi dạt khỏi nhau theo thời gian. Semantic layer / metrics layer giải quyết đúng chỗ này bằng một nguyên tắc:
Định nghĩa mỗi metric MỘT LẦN, tập trung, dạng code — rồi mọi công cụ hỏi cùng câu đều nhận cùng một đáp án.
Nó là nguồn sự thật duy nhất (single source of truth) về định nghĩa chỉ số — không phải về dữ liệu thô (đó là việc của kho), mà về cách tính toán và diễn giải dữ liệu thành con số nghiệp vụ. Semantic layer nằm giữa kho dữ liệu và các công cụ tiêu thụ: mọi truy vấn metric đi qua nó, nên định nghĩa không thể phân kỳ.
Điểm mấu chốt của sơ đồ: không có mũi tên nào đi thẳng từ warehouse tới công cụ BI. Mọi con đường tới metric đều bắt buộc qua semantic layer — đó là điều biến nó thành single source of truth thay vì chỉ là "một chỗ chép định nghĩa".
Vấn đề nó giải quyết: metric drift
Trước semantic layer, một tổ chức trưởng thành thường rơi vào tình trạng gọi là metric drift (chỉ số trôi dạt). Cùng một cái tên "doanh thu" (revenue), "khách hàng hoạt động" (active customer), "tỷ lệ nợ xấu" (NPL) nhưng công thức khác nhau ở mỗi nơi:
| Nơi định nghĩa | "Doanh thu" được tính là | Rủi ro |
|---|---|---|
| Power BI (phòng TC) | SUM(amount) trừ hoàn tiền, gồm thuế | — |
| Looker (phòng KD) | SUM(amount) không trừ hoàn tiền | Cao hơn TC |
| SQL notebook | SUM(gross) theo ngày đặt | Lệch kỳ |
| Bảng tổng hợp cũ | công thức từ 2 năm trước, đã lỗi | Sai âm thầm |
Mỗi định nghĩa sống trong một công cụ khép kín, không ai thấy công thức của người khác, không có review, không có version. Khi logic đổi (ví dụ đổi cách ghi nhận hoàn tiền), phải đi sửa N chỗ — và luôn sót. Semantic layer kéo toàn bộ N định nghĩa đó về một file code duy nhất, được review, được test, được versioned trong Git.
Thành phần của một semantic model
Một tầng ngữ nghĩa mô tả dữ liệu bằng một số khái niệm chung (thuật ngữ khác nhau đôi chút giữa các công cụ, nhưng ý tưởng chung):
- Entity / semantic model — thực thể nghiệp vụ được mô hình hoá, thường ánh xạ tới một bảng ở tầng gold (ví dụ
orders,customers). Mỗi entity khai báo khoá (primary/foreign key) để nối được với entity khác. - Dimension (chiều) — thuộc tính để cắt lát và nhóm (group by / filter):
order_date,customer_segment,product_category,region. Chiều thời gian thường được đánh dấu riêng để hỗ trợ cuộn theo ngày/tuần/tháng. - Measure (đại lượng) — một phép tổng hợp cột thô:
SUM(amount),COUNT(order_id),SUM(is_refunded). Measure là "nguyên liệu" chưa phải chỉ số hoàn chỉnh. - Metric (chỉ số) — định nghĩa nghiệp vụ hoàn chỉnh xây trên measure, có ý nghĩa để trình bày:
revenue = SUM(amount) - SUM(refund),npl_ratio = nợ_xấu / tổng_dư_nợ. Metric có thể là ratio (tỷ lệ), derived (dẫn xuất từ metric khác), hoặc cumulative (luỹ kế theo thời gian). - Join path (đường nối) — semantic layer biết các entity nối với nhau qua khoá nào, nên khi bạn hỏi "doanh thu theo
customer_segment" màrevenuenằm ởorderscòncustomer_segmentnằm ởcustomers, nó tự dựng đúng join — bạn không viết join tay, không sợ nối sai gây nhân đôi (fan-out).
Chính khả năng tự lắp join theo yêu cầu này là thứ khiến semantic layer mạnh hơn một bảng tổng hợp cố định: cùng một tập metric + dimension, người dùng cắt lát theo bất kỳ tổ hợp nào, tầng ngữ nghĩa sinh SQL đúng cho từng tổ hợp.
Từ một định nghĩa tới nhiều nơi tiêu thụ
Vòng đời của một câu hỏi qua semantic layer diễn ra như sau: người dùng (hoặc công cụ) yêu cầu metric + các dimension muốn cắt; tầng ngữ nghĩa tra định nghĩa đã đăng ký, dựng SQL (chọn đúng bảng, đúng join path, đúng phép tổng hợp), đẩy xuống kho chạy, rồi trả kết quả. Một định nghĩa — nhiều đường vào, cùng một công thức.
Trong thời AI, nhánh cuối cùng ngày càng quan trọng: một AI agent hỏi "doanh thu tháng trước" nếu đi qua semantic layer sẽ nhận con số đã được kiểm định thay vì tự bịa một câu SQL có thể sai định nghĩa. Semantic layer trở thành "lớp chống ảo giác về số liệu" cho agent.
Công cụ: các cài đặt tiêu biểu
Không có một chuẩn duy nhất; đây là các hiện thực phổ biến, mỗi loại một triết lý:
- dbt Semantic Layer (MetricFlow). Định nghĩa metric ngay trong dbt project — cạnh chính các model sinh ra dữ liệu (xem dbt tổng quan). MetricFlow là engine dựng SQL từ các semantic model YAML. Downstream (Tableau, Power BI, Hex, Mode, Sigma, Lightdash) truy vấn metric qua API/JDBC, luôn nhận cùng định nghĩa. Ưu điểm: metric sống cùng repo transform, cùng CI, cùng lineage.
- Cube — headless BI. Tách hẳn tầng ngữ nghĩa khỏi công cụ trực quan hoá, phơi metric qua REST / GraphQL / SQL API để bất kỳ consumer nào (BI, notebook, app nhúng, agent) dùng chung một định nghĩa. Có thêm caching (pre-aggregation) để tăng tốc.
- Looker — LookML. Ngôn ngữ mô hình hoá ngữ nghĩa tích hợp trong Looker, trưởng thành từ ~2014 — bản mẫu của tư tưởng "định nghĩa metric sống cạnh công cụ BI". LookML khai báo
dimension,measure,explore(join path); mọi báo cáo Looker chạy trên cùng model. - Headless BI (khái niệm). Kiến trúc tách logic nghiệp vụ + governance ra khỏi mọi công cụ hiển thị. Metric phơi qua API chuẩn; công cụ nào cũng chỉ là một "cái đầu" hiển thị cắm vào cùng một "thân" ngữ nghĩa. Cube là ví dụ điển hình; dbt Semantic Layer cũng đi theo hướng này. Lợi ích: đổi công cụ BI không phải viết lại định nghĩa metric.
Ví dụ định nghĩa metric
dbt Semantic Layer (MetricFlow) — semantic model + metric dạng YAML, đặt cạnh các model dbt:
# models/marts/semantic/orders.yml (minh hoạ MetricFlow)
semantic_models:
- name: orders
model: ref('fct_orders') # trỏ tới bảng gold ở marts
entities:
- name: order_id
type: primary
- name: customer # khoá ngoại để nối sang customers
type: foreign
expr: customer_key
dimensions:
- name: order_date
type: time
type_params: { time_granularity: day }
- name: order_status
type: categorical
measures:
- name: amount_sum
agg: sum
expr: amount
- name: refund_sum
agg: sum
expr: refund_amount
metrics:
# định nghĩa "doanh thu" MỘT LẦN — dùng lại khắp nơi
- name: revenue
label: "Doanh thu (đã trừ hoàn tiền)"
type: derived
type_params:
expr: amount_sum - refund_sum
metrics:
- name: amount_sum
- name: refund_sum
Cube — cùng ý tưởng, cú pháp riêng, phơi qua REST/GraphQL/SQL API:
# schema/Orders.yml (minh hoạ Cube)
cubes:
- name: orders
sql_table: analytics.fct_orders
joins:
- name: customers # join path khai báo sẵn
sql: "{orders}.customer_key = {customers}.customer_key"
relationship: many_to_one
dimensions:
- name: order_date
sql: order_date
type: time
- name: status
sql: order_status
type: string
measures:
- name: revenue # metric định nghĩa 1 nơi
sql: "amount - refund_amount"
type: sum
Với cả hai, một consumer chỉ cần xin revenue cắt theo customer.segment — engine tự dựng SQL với đúng join orders → customers; không ai viết lại công thức amount - refund_amount ở tầng BI nữa.
Metrics-as-code & governance
Điểm khiến semantic layer hiện đại khác với "một tài liệu Excel định nghĩa chỉ số" là nó là code:
- Versioned trong Git. Mỗi thay đổi định nghĩa metric là một commit — có lịch sử, biết ai đổi, đổi gì, khi nào. Đảo ngược được.
- Code review. Đổi công thức NPL phải qua pull request, có người duyệt — không còn ai lặng lẽ sửa công thức trong một dashboard.
- Test được. Có thể viết test kiểm tra metric không âm, tỷ lệ nằm trong [0,1], khớp với con số đối chiếu — ghép với data quality tests (xem Governance & Data Quality). Ghép cùng lineage của dbt, biết metric phụ thuộc bảng nào.
- Lineage & trust. Vì metric tham chiếu model qua
ref(), ta truy được từ con số trên dashboard ngược về cột nguồn — nền tảng của governance và kiểm toán.
Đây chính là tinh thần metrics-as-code: đối xử với định nghĩa chỉ số như phần mềm, hưởng mọi kỷ luật kỹ thuật (review, test, CI/CD, version) mà lâu nay chỉ code mới có. Governance chuyển từ "niềm tin và tài liệu tĩnh" sang "quy trình kỹ thuật cưỡng chế được".
Quan hệ với mô hình chiều: semantic layer đặt TRÊN star/OBT
Một hiểu nhầm phổ biến: semantic layer thay thế mô hình chiều. Không. Nó đặt lên trên tầng gold đã mô hình hoá — dù tầng đó là star schema (Kimball) hay One Big Table (xem OBT / wide table):
- Tầng gold trả lời "dữ liệu hình gì" — fact/dimension, grain, các bảng đã sạch và conform. Đây là cấu trúc vật lý dữ liệu nằm.
- Tầng semantic trả lời "con số nghĩa là gì" — công thức metric, cách nối, cách cắt lát. Đây là ý nghĩa nghiệp vụ đọc trên cấu trúc đó.
Hai tầng bổ trợ nhau. Semantic layer rất hợp với star schema: entity ↔ bảng dim/fact, join path ↔ quan hệ fact–dimension của Kimball, measure ↔ cột đo trên bảng fact. Nó cũng chạy tốt trên OBT (khi mọi thứ đã phẳng, join path đơn giản hơn, chủ yếu chỉ còn measure/metric). Thực tế, một mart star sạch làm nền lý tưởng cho semantic layer: khoá rõ, grain rõ, chiều conform — semantic layer chỉ việc khai báo công thức phía trên.
Nói ngắn gọn cho dễ nhớ: mô hình chiều lo cấu trúc, semantic layer lo định nghĩa. Bài này là phần mở rộng chuyên sâu của ý "semantic/metrics layer" đã nêu trong Data Modeling hiện đại: OBT & metrics.
Use case thực tế
Ngân hàng NCB — thống nhất chỉ số "tỷ lệ nợ xấu (NPL)" (số liệu minh hoạ). NPL được ba nơi dùng: phòng rủi ro báo cáo nội bộ, ban giám đốc ra quyết định, và báo cáo gửi cơ quan quản lý. Ba nơi từng tính ba kiểu:
- Phòng rủi ro: tử số = dư nợ nhóm 3–5, mẫu số = tổng dư nợ cho vay → 1,82%.
- Ban giám đốc (dashboard cũ): mẫu số gồm cả cam kết ngoại bảng → 1,64%.
- Báo cáo quản lý: chốt số theo ngày EOD cuối tháng, cách phân loại nợ hơi khác → 1,91%.
Ba con số cho cùng một chỉ tiêu gây tranh cãi và rủi ro tuân thủ. Giải pháp: đưa định nghĩa NPL vào semantic layer (dbt Semantic Layer hoặc LookML) — một công thức tử số/mẫu số, một quy tắc phân loại nhóm nợ, một mốc thời gian EOD chuẩn (liên hệ nghiệp vụ phân loại nợ và số liệu EOD của kho). Từ đó Power BI của ban giám đốc, báo cáo rủi ro, và cả agent hỏi tự nhiên "NPL tháng 6" đều đọc cùng metric → cùng một con số 1,82%. Khi hội đồng quyết định đổi cách xử lý nợ tái cơ cấu, chỉ sửa một PR trong repo semantic, review, merge — mọi nơi cập nhật đồng loạt, có lịch sử để kiểm toán.
Ghi nhớ
- Vấn đề: không có semantic layer, mỗi công cụ BI tự định nghĩa metric (doanh thu, NPL...) → nhiều con số khác nhau cho cùng chỉ tiêu (metric drift), cãi nhau "số của ai đúng".
- Giải pháp: định nghĩa mỗi metric MỘT LẦN, tập trung, dạng code → single source of truth cho định nghĩa chỉ số; mọi consumer dùng lại nhất quán.
- Vị trí: semantic layer nằm giữa warehouse và các công cụ tiêu thụ; mọi truy vấn metric bắt buộc đi qua nó — đó là điều làm nó thành SSoT.
- Thành phần: entity (thực thể + khoá), dimension (cắt lát), measure (tổng hợp thô), metric (định nghĩa nghiệp vụ hoàn chỉnh), join path (tự dựng join đúng theo yêu cầu).
- Công cụ: dbt Semantic Layer / MetricFlow (metric cạnh model dbt), Cube (headless BI, phơi REST/GraphQL/SQL), LookML (metric cạnh BI — bản mẫu). Headless BI = tách logic khỏi công cụ hiển thị.
- Metrics-as-code: định nghĩa chỉ số được versioned, review, test, lineage — governance chuyển từ tài liệu tĩnh sang quy trình kỹ thuật cưỡng chế được.
- Quan hệ mô hình chiều: semantic layer đặt TRÊN star/OBT, không thay thế — mô hình chiều lo cấu trúc, semantic layer lo định nghĩa; star sạch là nền lý tưởng.
- Thời AI: agent hỏi số liệu qua semantic layer nhận con số đã kiểm định thay vì tự bịa SQL.
Nguồn tham khảo
- dbt Semantic Layer & MetricFlow — dbt Documentation — semantic model, metric YAML, engine dựng SQL.
- MetricFlow — cấu trúc semantic model (entities/dimensions/measures/metrics) — dbt Documentation — chi tiết các thành phần và join path.
- Cube Documentation — headless BI / semantic layer — phơi metric qua REST/GraphQL/SQL API, pre-aggregation.
- LookML — Looker Documentation (Google Cloud) — mô hình hoá ngữ nghĩa cạnh công cụ BI (dimension/measure/explore).
- Joe Reis & Matt Housley, Fundamentals of Data Engineering (O'Reilly) — tầng phục vụ, semantic layer và vai trò trong vòng đời dữ liệu.
- Ralph Kimball & Margy Ross, The Data Warehouse Toolkit (3rd ed., Kimball Group) — mô hình chiều (fact/dimension, conformed dimension) làm nền cho tầng ngữ nghĩa.
Bài trong series Data Modeling nâng cao: Tổng quan modeling nâng cao, One Big Table / wide table, Mô hình hoá dữ liệu ngân hàng. Liên quan: Data Modeling hiện đại: OBT & metrics, dbt tổng quan, Looker tổng quan.
Bài viết liên quan
So sánh các định dạng dữ liệu (CSV, JSON, XML, Avro, Parquet, ORC) và lý do lưu theo cột nhanh hơn cho phân tích. Bài đi sâu vào row vs columnar storage, nén (Snappy/gzip/zstd), schema evolution, OLTP vs OLAP, object storage và partitioning để tối ưu chi phí lẫn tốc độ truy vấn.
Data Engineering là ngành xây dựng và vận hành hệ thống biến dữ liệu thô thành dữ liệu sạch, tin cậy, sẵn sàng cho phân tích và AI. Bài giới thiệu vai trò Data Engineer trong vòng đời dữ liệu (nguồn → ingestion → storage → transformation → serving), phân biệt với Analyst/Scientist/ML Engineer, bức tranh hệ sinh thái công cụ và bài toán đưa dữ liệu core banking sang kho phân tích.
Stream processing là gì, khác biệt batch vs stream (bounded/unbounded), micro-batch (Spark) vs true streaming, Apache Flink là gì và định vị so với Spark Structured Streaming và Kafka Streams. Kiến trúc runtime JobManager/TaskManager, các tầng API, triết lý streaming-first và bối cảnh phát hiện gian lận ngân hàng.
Vì sao một máy không đủ và cần xử lý phân tán: từ MapReduce, Hadoop/HDFS đến Apache Spark in-memory. Kiến trúc driver–executor–cluster manager, các mức trừu tượng RDD/DataFrame/Dataset, cơ chế lazy evaluation với DAG, và vì sao shuffle (wide dependency) là phần tốn kém nhất. Kèm PySpark, Spark SQL và các kỹ thuật tối ưu (partition, broadcast join, cache, chống skew) cùng khi nào KHÔNG nên dùng Spark.
Cảm nhận của bạn
Bình luận
Chưa có bình luận. Hãy là người đầu tiên chia sẻ!