Looker 2 — LookML cơ bản: project, model, view

13 thg 7, 2026 3 lượt xem
#bi
#measure
#lookml
#looker
#view
#dimension

Mở đầu: LookML là ngôn ngữ, không phải giao diện

Ở bài Looker 1 — Tổng quan & kiến trúc mô hình hoá ta đã thấy Looker là một nền tảng BI xoay quanh một tầng ngữ nghĩa được mã hoá bằng LookML, và mọi câu hỏi của người dùng cuối cuối cùng biến thành SQL chạy trực tiếp trên warehouse. Bài này mở nắp chính cái tầng ngữ nghĩa đó: LookML thực sự trông như thế nào, gồm những loại file gì, viết một view ra sao, khai báo một model thế nào, và — mấu chốt — làm sao một dòng LookML lại biến thành một câu SELECT ... GROUP BY đẩy xuống warehouse.

Trước hết cần định vị đúng: LookML không phải giao diện kéo thả. Nó là một ngôn ngữ khai báo (declarative) — bạn mô tả dữ liệu có ý nghĩa gì, chứ không ra lệnh từng bước tính toán. Bạn không viết "hãy chạy SELECT rồi GROUP BY"; bạn khai báo "cột này là một chiều tên là ngày giao dịch", "phép đo doanh thu là tổng của cột amount". Việc dịch những khai báo đó thành SQL cụ thể là của engine sinh SQL trong Looker. Chính vì khai báo, LookML mang tính tái sử dụng: định nghĩa một lần, dùng ở mọi Explore, mọi Look, mọi Dashboard.

Một lưu ý quy ước xuyên suốt loạt bài: đây là công cụ BI, không phải SQL sandbox. Mọi đoạn LookML dưới đây là minh hoạ khái niệm — để đọc và hiểu cấu trúc, không phải để copy-paste chạy ở đâu đó.

Bức tranh tổng thể: một LookML project gồm gì

Một LookML project là một tập hợp các file mô tả toàn bộ mô hình dữ liệu — kết nối tới database, các bảng logic, các chiều, phép đo, và cách chúng nối với nhau. Project này gắn với một Git repository: mỗi thay đổi là một commit, có lịch sử, có thể review qua pull request, có thể rollback. Đây là điểm khiến LookML giống code hơn là cấu hình BI thông thường.

Trong project có vài loại file chính, phân biệt bằng phần mở rộng:

  • File model*.model.lkml: khai báo connection (kết nối tới warehouse nào), include các file view cần dùng, và các explore (điểm vào khám phá cho người dùng). Model là "cổng vào" cho một nhóm nghiệp vụ.
  • File view*.view.lkml: định nghĩa một bảng logic — ánh xạ tới một bảng/truy vấn trong warehouse, và khai báo các dimensionmeasure của bảng đó.
  • File dashboard*.dashboard.lkml: định nghĩa dashboard bằng mã (LookML dashboard), thay vì dựng thủ công trên giao diện.
  • File manifestmanifest.lkml: cấu hình cấp project (import project khác, localization, hằng số...).

Sơ đồ dưới đây minh hoạ quan hệ giữa các thành phần:

Điểm cần ghi vào đầu: model include view, model khai báo explore, view chứa dimension và measure. Ba tầng này là xương sống của mọi mô hình LookML.

View: bảng logic ánh xạ tới warehouse

View là đơn vị mô hình hoá cơ bản nhất. Một view mô tả một bảng có ý nghĩa — nó ánh xạ tới một bảng thật (hoặc một truy vấn) trong warehouse, rồi khai báo các trường (field) của bảng đó. View chưa biết nó sẽ được nối (join) với ai — chuyện join thuộc về explore ở bài sau. View chỉ trả lời: bảng này là gì, có những chiều và phép đo nào.

Liên kết tới bảng vật lý thực hiện bằng tham số sql_table_name:

view: orders {
  sql_table_name: analytics.public.orders ;;
  # ... dimension và measure ở đây
}

sql_table_name chỉ đơn giản là tên bảng đầy đủ trong warehouse (thường dạng schema.table hoặc project.dataset.table với BigQuery). Khi Looker sinh SQL, giá trị này trở thành mệnh đề FROM. Nếu không khai báo sql_table_name, Looker mặc định lấy tên bảng trùng tên view — nhưng viết rõ ra vẫn tốt hơn để tránh nhầm.

Bên trong view là hai loại trường quan trọng nhất: dimension (chiều) và measure (phép đo). Hiểu đúng sự khác nhau giữa hai loại này là hiểu được một nửa LookML.

Dimension: các chiều để nhóm và lọc

Dimension là một thuộc tính — một cột hoặc một biểu thức tính từ cột — dùng để nhóm (group by)lọc (filter). Trong SQL sinh ra, dimension xuất hiện ở mệnh đề GROUP BY và trong SELECT như các cột không tổng hợp. "Ngày giao dịch", "loại giao dịch", "chi nhánh", "trạng thái đơn" — đều là dimension.

Cú pháp cơ bản của một dimension:

dimension: status {
  type: string
  sql: ${TABLE}.status ;;
}

Ba mảnh cần chú ý:

  • type: kiểu của chiều. Các type thường dùng: string (chuỗi), number (số), date / time (thời gian), yesno (đúng/sai — sinh ra một biểu thức boolean), và tier (chia số thành các khoảng, ví dụ tuổi 0–18, 19–35...).
  • sql: biểu thức SQL định nghĩa giá trị của chiều, kết thúc bằng ;;. Thường là một cột (${TABLE}.status), nhưng cũng có thể là biểu thức (${TABLE}.first_name || ' ' || ${TABLE}.last_name).
  • Toán tử tham chiếu: ${TABLE} trỏ tới bảng nền của chính view hiện tại — nó sẽ được thay bằng bí danh (alias) thật khi sinh SQL. Còn ${ten_field} trỏ tới một field khác (dimension hoặc measure) trong mô hình, cho phép tái dùng logic thay vì lặp lại biểu thức SQL.

${field} chính là "chất keo" của LookML. Thay vì viết đi viết lại cùng một biểu thức cột, bạn định nghĩa nó một lần trong một dimension rồi tham chiếu bằng ${...} ở khắp nơi. Đây là cách LookML tránh trùng lặp và giữ tính nhất quán.

Với dữ liệu thời gian, LookML có một cấu trúc đặc biệt gọi là dimension_group kiểu time, sinh ra hàng loạt chiều dẫn xuất từ một cột timestamp (theo ngày, tuần, tháng, quý, năm...). Ta sẽ dùng nó trong ví dụ và use case bên dưới, và đào sâu ở bài Looker 4 — Dimensions & measures nâng cao.

Measure: các phép tổng hợp

Measure là một phép tổng hợp (aggregation) — nó cộng gộp nhiều dòng lại thành một con số. Trong SQL sinh ra, measure trở thành hàm tổng hợp như SUM(...), COUNT(...), AVG(...). "Tổng doanh thu", "số lượng đơn", "số khách hàng duy nhất" — đều là measure.

Cú pháp của một measure điển hình:

measure: total_amount {
  type: sum
  sql: ${amount} ;;
}

Chú ý điểm mấu chốt: measure total_amount không tham chiếu trực tiếp ${TABLE}.amount mà tham chiếu ${amount} — tức là một dimension khác tên amount. Measure phụ thuộc dimension: bạn thường định nghĩa một dimension cho cột thô trước, rồi xây measure tổng hợp lên trên nó. Điều này giữ nguyên tắc "định nghĩa cột một lần".

Các type measure hay dùng:

  • count: đếm số dòng (COUNT(*)). Không cần sql.
  • sum: cộng dồn các giá trị (SUM(...)).
  • average: trung bình (AVG(...)).
  • count_distinct: đếm số giá trị duy nhất (COUNT(DISTINCT ...)).
  • min / max: giá trị nhỏ nhất / lớn nhất.
  • number: một measure tính từ measure khác — không tự chạy hàm tổng hợp mà dùng biểu thức SQL sau tổng hợp, ví dụ tỷ lệ = ${measure_a} / NULLIF(${measure_b}, 0).

Nhóm number rất quan trọng cho các chỉ số tỷ lệ (tỷ lệ nợ xấu, tỷ suất lợi nhuận): bạn tạo hai measure tổng hợp riêng, rồi tạo measure number chia chúng cho nhau — nhờ vậy tỷ lệ luôn được tính đúng ở mọi mức độ nhóm. Looker còn nhiều type nâng cao (median, percentile, running_total, percent_of_total...) sẽ nói ở bài 4.

Model: connection, include, explore

Nếu view mô tả từng bảng, thì model là nơi ghép mọi thứ lại thành một cổng khám phá cho người dùng. Một file model làm ba việc:

  1. Gắn một connection: model trỏ tới đúng một kết nối database (một warehouse). Mọi Explore trong model này sẽ sinh SQL cho warehouse đó.
  2. Include các view: model phải khai báo những file view nào nó được dùng, bằng tham số include. View không tự động có mặt — phải include mới thấy.
  3. Khai báo explore: mỗi explore là một điểm vào mà người dùng cuối nhìn thấy và bắt đầu kéo thả từ đó. Explore quyết định "khám phá bắt đầu từ bảng nào" và (ở bài sau) "nối thêm bảng nào".

Ví dụ một model tối giản:

connection: "bigquery_prod"

include: "/views/*.view.lkml"

explore: orders {
  label: "Phân tích đơn hàng"
  description: "Khám phá đơn hàng theo ngày, trạng thái, doanh thu"
}

Ở đây explore: orders nói rằng người dùng có thể khám phá bắt đầu từ view orders. Vì view này đã có dimension (order_date, status) và measure (total_amount, order_count), người dùng sẽ thấy đúng những trường đó trong giao diện Explore. Explore này chưa join thêm bảng nào — nó chỉ dựa trên một view duy nhất, phù hợp để làm quen. Join giữa nhiều view là chủ đề của Looker 3 — Explores & joins.

Cách LookML sinh SQL

Đây là phần liên kết mọi thứ lại. Khi một người dùng vào Explore và chọn vài dimension cùng vài measure, Looker không chạy sẵn một truy vấn cố định. Nó đọc mô hình LookML để hiểu ý định, rồi sinh ra một câu SQL cụ thể và đẩy xuống warehouse (đúng tinh thần in-database ở bài tổng quan).

Quy tắc dịch rất dễ nhớ:

  • Mỗi dimension người dùng chọn → thêm vào SELECTGROUP BY.
  • Mỗi measure người dùng chọn → thêm hàm tổng hợp tương ứng vào SELECT.
  • sql_table_name của view → mệnh đề FROM.
  • Bộ lọc người dùng đặt → mệnh đề WHERE.

Ví dụ: người dùng mở Explore orders, chọn dimension status và measure total_amount. Looker sinh ra một câu SQL đại ý (minh hoạ, không phải để chạy):

SELECT
  orders.status        AS status,
  SUM(orders.amount)   AS total_amount
FROM analytics.public.orders AS orders
GROUP BY 1

Bạn thấy toàn bộ mảnh ghép hiện ra: SUM(orders.amount) đến từ measure total_amount (kiểu sum trên ${amount}), orders.status đến từ dimension status, FROM analytics.public.orders đến từ sql_table_name, và GROUP BY 1 xuất hiện vì có ít nhất một measure kèm một dimension. Nếu người dùng thêm dimension order_date, nó vào SELECTGROUP BY; nếu thêm bộ lọc "chỉ đơn hoàn tất", một mệnh đề WHERE xuất hiện. Người dùng không viết bất kỳ dòng SQL nào — họ chỉ chọn, còn Looker dịch.

Điểm hay của cơ chế này: vì công thức tổng hợp nằm trong measure (một chỗ duy nhất), ai chọn total_amount cũng nhận đúng cùng một SUM. Đó là "single source of truth" về metric ở dạng cụ thể nhất.

IDE, dev mode và Git

Bạn viết LookML trong Looker IDE — một môi trường soạn thảo ngay trong trình duyệt, có file browser, object browser, và nút validate. Quy trình chuẩn:

  1. Bật Development Mode: mọi thay đổi bạn gõ nằm trong một "hộp cát" riêng, không ảnh hưởng người dùng đang chạy production.
  2. Sửa và validate: Looker kiểm tra cú pháp và tham chiếu (LookML phân biệt hoa thường với tên field và đường dẫn — sai chữ hoa là lỗi). Bạn xem thử kết quả ngay trong Explore ở dev mode.
  3. Commit lên Git: khi ưng ý, bạn commit thay đổi kèm thông điệp, tạo một điểm mốc trong lịch sử.
  4. Deploy lên Production: đẩy commit thành phiên bản mà toàn bộ người dùng nhìn thấy.

Sự tách bạch dev mode vs production cộng với Git chính là thứ khiến LookML an toàn ở quy mô lớn: nhiều developer cùng làm, mỗi người trên nhánh riêng, thay đổi được review, và không ai vô tình làm hỏng dashboard của cả tổ chức.

Use case thực tế: mô hình hoá bảng giao dịch

Bối cảnh: Một ngân hàng số có bảng giao dịch transactions trong BigQuery, gồm các cột: txn_id, txn_ts (thời điểm giao dịch), txn_type (loại: nạp/rút/chuyển khoản/thanh toán), amount (số tiền), customer_id. Đội dữ liệu muốn cho người dùng nghiệp vụ tự trả lời "tổng tiền giao dịch theo loại theo tháng" mà không cần biết SQL.

Bước 1 — Viết view (minh hoạ) với các dimension ngày/loại và measure tổng tiền:

view: transactions {
  sql_table_name: banking.core.transactions ;;

  dimension: txn_id {
    primary_key: yes
    type: number
    sql: ${TABLE}.txn_id ;;
  }

  # Nhóm chiều thời gian: sinh ra txn theo ngày/tuần/tháng/quý/năm
  dimension_group: txn {
    type: time
    timeframes: [date, week, month, quarter, year]
    sql: ${TABLE}.txn_ts ;;
  }

  dimension: txn_type {
    type: string
    sql: ${TABLE}.txn_type ;;
  }

  dimension: amount {
    type: number
    sql: ${TABLE}.amount ;;
  }

  # Đếm số giao dịch
  measure: txn_count {
    type: count
  }

  # Tổng tiền giao dịch
  measure: total_amount {
    type: sum
    sql: ${amount} ;;
    value_format_name: decimal_0
  }

  # Giá trị giao dịch trung bình
  measure: avg_amount {
    type: average
    sql: ${amount} ;;
  }
}

Bước 2 — Khai báo model (minh hoạ) gắn connection, include view và mở explore:

connection: "bigquery_prod"

include: "/views/transactions.view.lkml"

explore: transactions {
  label: "Phân tích giao dịch"
  description: "Tổng tiền và số lượng giao dịch theo loại và thời gian"
}

Bước 3 — Người dùng khám phá. Một chuyên viên vận hành mở Explore "Phân tích giao dịch", chọn dimension Txn MonthTxn Type, chọn measure Total Amount. Looker sinh SQL đại ý:

SELECT
  FORMAT_TIMESTAMP('%Y-%m', transactions.txn_ts) AS txn_month,
  transactions.txn_type                          AS txn_type,
  SUM(transactions.amount)                        AS total_amount
FROM banking.core.transactions AS transactions
GROUP BY 1, 2
ORDER BY 1

Câu này chạy trực tiếp trên BigQuery, trả về bảng "tổng tiền theo loại theo tháng". Người dùng có thể đổi sang Txn Quarter, thêm measure Txn Count, hay lọc txn_type = 'transfer' — mỗi lựa chọn đổi SQL tương ứng, nhưng công thức SUM(amount) luôn đến từ measure total_amount được kiểm soát một chỗ. Đội dữ liệu chỉ cần commit view và model này lên Git một lần; từ đó hàng trăm người dùng tự phục vụ với con số nhất quán.

Ghi nhớ

  • LookML là ngôn ngữ khai báo, không phải giao diện: bạn mô tả dữ liệu có ý nghĩa gì, Looker lo việc sinh SQL. Định nghĩa một lần → tái dùng khắp nơi.
  • Cấu trúc project: *.model.lkml (connection + include + explore), *.view.lkml (bảng logic + dimension/measure), *.dashboard.lkml, manifest.lkml. Project gắn Git.
  • View ánh xạ tới bảng warehouse qua sql_table_name (→ mệnh đề FROM), và chứa các dimension, measure.
  • Dimension = thuộc tính để group by / filter (type string/number/date/yesno/tier; sql: ${TABLE}.cot ;;). ${TABLE} trỏ bảng nền, ${ten_field} trỏ field khác để tái dùng.
  • Measure = phép tổng hợp (count, sum, average, count_distinct, min/max, và number cho tỷ lệ). Measure phụ thuộc dimension — thường tổng hợp trên một dimension đã khai báo.
  • Model gắn một connection, include các view, và khai báo explore — điểm vào cho người dùng.
  • Cách sinh SQL: dimension → SELECT + GROUP BY; measure → hàm tổng hợp trong SELECT; sql_table_nameFROM; bộ lọc → WHERE. Người dùng chỉ chọn, Looker dịch.
  • Quy trình: viết trong Looker IDE, tách dev mode vs production, validate, commit lên Git, rồi deploy. LookML phân biệt hoa thường.
  • Đây là công cụ BI, không phải SQL sandbox: mọi đoạn LookML ở đây là minh hoạ để hiểu khái niệm.

Bài tiếp theo

Ta đã dựng được một view và một explore đơn bảng. Bước tiếp theo là gom nhiều bảng lại: Looker 3 — Explores & joins sẽ chỉ cách nối các view trong explore bằng sql_onrelationship. Sau đó, để làm chủ các chiều và phép đo phức tạp hơn (dimension_group thời gian, tier, measure tỷ lệ, filtered measure), hãy xem Looker 4 — Dimensions & measures nâng cao. Và để có bức tranh nền, luôn có thể quay lại Looker 1 — Tổng quan & kiến trúc mô hình hoá.

Bài viết liên quan

Phân biệt ước lượng điểm và ước lượng khoảng, cách xây khoảng tin cậy (CI) bằng margin of error z*·SE / t*·SE, đánh đổi mức 90/95/99%, và cách DIỄN GIẢI ĐÚNG khoảng tin cậy (95% CI không phải xác suất tham số nằm trong khoảng). Có CI cho trung bình và cho tỷ lệ, ảnh hưởng của cỡ mẫu, cùng ví dụ ngân hàng về tỷ lệ nợ xấu và số dư trung bình.

13 thg 7, 2026 4

Kimball dimensional modeling: bảng fact/dimension, star vs snowflake, grain, và Slowly Changing Dimension.

13 thg 7, 2026 3

Khối OLAP, các thao tác drill-down/roll-up/slice & dice/pivot, OLAP vs OLTP và ROLAP/MOLAP/HOLAP.

13 thg 7, 2026 3

Từ nguồn dữ liệu qua ETL/ELT vào Data Warehouse, Data Mart đến dashboard; staging, ODS, batch vs streaming.

13 thg 7, 2026 3