Ngân hàng đề — Google Cloud Associate Data Practitioner

Tìm thấy 333 câu.

Câu 61 Data Pipeline Orchestration

A data analyst needs to write a query in BigQuery to rank employees based on their monthly sales figures. The source table, sales_performance, contains employee_id, sales_month, and total_sales.

The business has a strict requirement for the report: rank employees from highest to lowest sales within each month. If two or more employees have the exact same sales total (a tie), they must receive the same rank number. Critically, the ranking sequence must continue with the next consecutive integer after the tie, with no gaps.

For example, if the top four sales figures are $1000, $950, $950, $900, the required ranks must be 1, 2, 2, 3.

Which window function should the analyst use to meet this "no-gap" ranking requirement?

  1. A

    RANK()

  2. B

    NTILE(100)

  3. C

    ROW_NUMBER()

  4. D

    DENSE_RANK()

Xem giải thích

Đáp án

D — DENSE_RANK()

Vì sao đúng

Đề nêu hai yêu cầu về cách xếp hạng: giá trị bằng nhau phải cùng hạng, và dãy hạng phải LIÊN TỤC, KHÔNG có khoảng trống. Chỉ DENSE_RANK() thoả cả hai.

⚠ Điểm mấu chốt — so ba hàm trên chính ví dụ của đề:

Doanh số: 1000, 950, 950, 900

ROW_NUMBER()  → 1, 2, 3, 4
                ⚠ hai người bằng nhau
                  vẫn khác hạng

RANK()        → 1, 2, 2, 4
                ⚠ cùng hạng, nhưng
                  BỎ QUA số 3

DENSE_RANK()  → 1, 2, 2, 3      ← đề yêu cầu
                ✓ cùng hạng
                ✓ liên tục, không hụt

⚠ Truy vấn hoàn chỉnh:

SELECT
  employee_id,
  sales_month,
  total_sales,
  DENSE_RANK() OVER (
    PARTITION BY sales_month
    ORDER BY total_sales DESC
  ) AS hang
FROM `du_an.sales_performance`;
        ↓
    PARTITION BY sales_month
      → xếp hạng RIÊNG trong TỪNG THÁNG
    ORDER BY total_sales DESC
      → cao nhất là hạng 1

⚠ Mẹo nhớ tên gọi:

DENSE = "đặc, không có lỗ hổng"
        ↓
    → DENSE_RANK cho dãy ĐẶC,
      không hụt số
        ↓
    RANK thường thì "thưa" — có lỗ hổng
    sau mỗi lần đồng hạng

Vì sao các phương án khác sai

  • A (RANK()) — đây là phương án gần nhất và đúng vế "cùng hạng khi bằng nhau", nhưng nó bỏ qua số tiếp theo: cho ra 1, 2, 2, 4 thay vì 1, 2, 2, 3. Đề cấm điều này.

  • C (ROW_NUMBER()) — luôn cho số khác nhau, hai người bằng nhau vẫn bị xếp khác hạng.

  • B (NTILE(100)) — chia dữ liệu thành 100 nhóm bằng nhau (phân vị), không phải xếp hạng theo yêu cầu.

Ghi nhớ

⚠ Bốn hàm xếp hạng — bảng phải thuộc: | Hàm | Với 1000, 950, 950, 900 | Đặc điểm | |---|---|---| | ROW_NUMBER() | 1, 2, 3, 4 | luôn khác nhau | | RANK() | 1, 2, 2, 4 | cùng hạng, CÓ khoảng trống | | DENSE_RANK() | 1, 2, 2, 3 | cùng hạng, KHÔNG khoảng trống | | NTILE(n) | chia thành n nhóm | phân vị | | Mẹo nhớ | DENSE = đặc = không hụt số |

Từ khoá nhận diện:

"đồng hạng, không được hụt số" → DENSE_RANK() "đồng hạng, hạng tiếp theo nhảy cóc" → RANK() "mỗi dòng một số duy nhất" → ROW_NUMBER() "chia thành nhóm phần trăm" → NTILE() "lấy dòng mới nhất mỗi nhóm" → ROW_NUMBER() + WHERE rn = 1

Cấu trúc của hàm cửa sổ Thành phần
OVER (...) bắt buộc — đánh dấu hàm cửa sổ
PARTITION BY chia thành các nhóm độc lập
ORDER BY thứ tự trong nhóm
ROWS/RANGE BETWEEN khung cửa sổ trượt
Đặc điểm GIỮ NGUYÊN số dòng, khác GROUP BY
Các hàm cửa sổ hay dùng khác Hàm
LAG(x, n) / LEAD(x, n) giá trị dòng trước / sau
SUM(x) OVER (...) cộng dồn
AVG(x) OVER (... ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) trung bình trượt
FIRST_VALUE / LAST_VALUE giá trị đầu / cuối nhóm
PERCENT_RANK, CUME_DIST phân vị
Lấy top-N theo từng nhóm Cách
Bọc trong truy vấn con WHERE hang <= 3
Dùng ROW_NUMBER() khi cần đúng N dòng, không kể đồng hạng
Dùng DENSE_RANK() khi muốn lấy HẾT những người đồng hạng
Cách gọn của BigQuery ARRAY_AGG(... ORDER BY ... LIMIT n)
Lưu ý không lọc được hàm cửa sổ ngay trong WHERE
Vì sao không lọc được trong WHERE Nội dung
Thứ tự thực thi WHERE chạy TRƯỚC SELECT
Hàm cửa sổ tính ở bước SELECT
Vì vậy phải bọc trong subquery hoặc CTE
Cú pháp gọn của BigQuery QUALIFY — lọc trực tiếp trên hàm cửa sổ
Ví dụ QUALIFY DENSE_RANK() OVER (...) <= 3

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Có trường hợp đồng hạng không | GROUP BY sales_month, total_sales HAVING COUNT(*) > 1 | | Hạng có hụt số không | SELECT DISTINCT hang ORDER BY 1 | | Xếp hạng đúng phạm vi chưa | kiểm tra PARTITION BY có đúng cột tháng |

Và một cú pháp rất đáng biết của BigQuery giúp truy vấn kiểu này gọn hơn hẳn: QUALIFY. Thay vì bọc cả truy vấn vào một lớp subquery chỉ để lọc theo hạng, QUALIFY DENSE_RANK() OVER (...) <= 3 làm đúng việc đó trong một dòng — và truy vấn đọc lên giống hệt cách bạn mô tả yêu cầu bằng lời.

Câu 62 Data Pipeline Orchestration

A new application publishes status messages to a Pub/Sub topic. You need to ensure every single message sent to this topic is processed by two different and independent downstream systems. One system is a Dataflow pipeline for alerting, and the other is a Cloud Function for logging.

How should you configure the Pub/Sub resources to ensure both systems receive every message?

  1. A Configure the topic to directly push messages to both a Dataflow job and a Cloud Function.
  2. B Create two separate Pub/Sub topics, one for each system.
  3. C Create one topic and have both systems read from a single, shared subscription.
  4. D Create one topic and two separate subscriptions, one for each downstream system.
Xem giải thích

Đáp án

D — Tạo MỘT topic và HAI subscription riêng, mỗi hệ thống một cái.

Vì sao đúng

Trong Pub/Sub, mỗi subscription nhận một BẢN SAO ĐỘC LẬP của MỌI thông điệp trong topic. Đó chính là cơ chế để hai hệ thống hạ nguồn đều nhận đủ mọi thông điệp.

⚠ Điểm mấu chốt — subscription là ranh giới của việc phân phát:

        TOPIC "trang-thai"
              │
    ┌─────────┴─────────┐
    │                   │
SUBSCRIPTION A     SUBSCRIPTION B
    │                   │
Dataflow            Cloud Function
(cảnh báo)          (ghi log)
        ↓
    ⚠ MỖI subscription có HÀNG ĐỢI RIÊNG
    ⚠ MỖI subscription nhận ĐỦ mọi thông điệp
    ⚠ Ack ở A KHÔNG ảnh hưởng B

⚠ ⚠ Vì sao dùng CHUNG một subscription là sai hoàn toàn:

Hai hệ thống cùng đọc MỘT subscription
        ↓
    Pub/Sub coi chúng là HAI WORKER
    của CÙNG một bên nhận
        ↓
    → thông điệp được CHIA cho hai bên
    → mỗi thông điệp chỉ MỘT bên nhận
        ↓
    ⚠ Dataflow nhận ~50%
    ⚠ Cloud Function nhận ~50%
    ⚠ Không bên nào có đủ dữ liệu
        ↓
    → đây là lỗi thiết kế kinh điển

⚠ Vì sao hai topic riêng cũng không đúng:

Hai topic
        ↓
    Ứng dụng phải PUBLISH HAI LẦN
        ↓
    ⚠ Publish lần một thành công,
      lần hai lỗi → dữ liệu LỆCH nhau
    ⚠ Thêm hệ thống thứ ba → SỬA MÃ ứng dụng
        ↓
    Trái hẳn với mục tiêu TÁCH RỜI

⚠ Tạo cấu hình đúng:

gcloud pubsub topics create trang-thai

gcloud pubsub subscriptions create sub-canh-bao \
  --topic=trang-thai            # Dataflow pull

gcloud pubsub subscriptions create sub-ghi-log \
  --topic=trang-thai \
  --push-endpoint=https://...  # Cloud Function push

Xem thêm câu #12949 (cùng lô): cùng tình huống fan-out nhưng hỏi CHỌN DỊCH VỤ nào → khoá là Pub/Sub. Câu này hỏi CẤU HÌNH thế nào → một topic, hai subscription. Hai câu bổ sung nhau, hoàn toàn nhất quán.

Vì sao các phương án khác sai

  • C (một topic, hai hệ thống đọc chung MỘT subscription) — đây là phương án bẫy chính: thông điệp bị CHIA ĐÔI giữa hai bên nhận, không bên nào có đủ.

  • B (hai topic riêng) — buộc ứng dụng publish hai lần, dễ lệch dữ liệu, và mất tính tách rời.

  • A (topic đẩy thẳng tới cả hai) — topic KHÔNG đẩy trực tiếp tới đâu cả; việc phân phát luôn đi qua subscription.

Ghi nhớ

⚠ Topic ↔ Subscription — bảng phải thuộc: | Khái niệm | Vai trò | |---|---| | Topic | nơi PUBLISH thông điệp | | Subscription | hàng đợi RIÊNG cho MỘT bên nhận logic | | Nhiều subscription trên một topic | mỗi cái nhận ĐỦ mọi thông điệp (fan-out) | | Nhiều worker trên MỘT subscription | CHIA việc cho nhau (load balancing) | | Nhớ | fan-out ở tầng SUBSCRIPTION, không phải tầng worker |

Từ khoá nhận diện:

"hai hệ thống độc lập đều nhận đủ" → hai SUBSCRIPTION "nhiều worker chia tải cùng một việc" → một subscription, nhiều worker "nạp thẳng vào BigQuery" → BigQuery subscription "ghi thành tệp trong GCS" → Cloud Storage subscription "lọc bớt thông điệp cho một bên nhận" → subscription filter

Bốn loại subscription Loại
Pull bên nhận tự lấy — Dataflow, worker
Push Pub/Sub gọi HTTP — Cloud Run, Functions
BigQuery subscription ghi thẳng vào bảng, không cần mã
Cloud Storage subscription ghi thẳng thành tệp
Đề này pull cho Dataflow, push cho Cloud Function
Subscription filter — tính năng đáng biết Nội dung
Việc chỉ nhận thông điệp thoả điều kiện
Lọc theo thuộc tính (attributes) của thông điệp
Ví dụ attributes.loai = "canh_bao"
Lợi ích mỗi bên nhận chỉ lấy phần mình cần
Lưu ý không lọc theo NỘI DUNG thông điệp
Đặt khi tạo subscription — không sửa được sau
Cấu hình quan trọng cho mỗi subscription Cấu hình
--ack-deadline dài hơn thời gian xử lý
--message-retention-duration mặc định 7 ngày
Dead-letter topic thông điệp hỏng đi đâu
--max-delivery-attempts ngưỡng chuyển dead-letter
Retry policy backoff
Ordering key thứ tự trong cùng khoá
Theo dõi từng subscription riêng Chỉ số
num_undelivered_messages backlog của CHÍNH subscription đó
oldest_unacked_message_age thông điệp cũ nhất
Vì sao quan trọng một bên nhận chậm không kéo bên kia xuống, nhưng backlog của nó vẫn phình
Cảnh báo đặt riêng cho từng subscription
Nếu backlog vượt thời gian giữ thông điệp bị MẤT

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Topic có mấy subscription | gcloud pubsub topics list-subscriptions <topic> | | Mỗi bên nhận có tồn đọng không | num_undelivered_messages theo từng subscription | | Hai bên có nhận đủ như nhau không | so số bản ghi ở hai đích |

Và một phép kiểm tra rất đáng làm sau khi dựng xong kiến trúc này: so số bản ghi ở hai đích trong cùng một khoảng thời gian. Nếu hai con số xấp xỉ một nửa của nhau, gần như chắc chắn hai hệ thống đang chia nhau một subscription duy nhất — triệu chứng đó dễ bị nhầm thành "một bên xử lý chậm" và có thể tồn tại rất lâu trước khi ai đó phát hiện.

Câu 63 Data Analysis and Presentation

A sales operations analyst is responsible for tracking regional sales performance. The quarterly sales quotas for each region are maintained by managers in a Google Sheet. The real-time, transactional sales data is stored in a BigQuery table named company_sales.all_transactions.

The analyst needs to create a single report inside Google Sheets that joins the sales quota data from the Sheet with the aggregated actual sales data from BigQuery. The report must be easily refreshable to pull the latest sales figures.

Which tool is the most direct and efficient solution for the analyst to accomplish this?

  1. A

    Looker

  2. B

    Dataflow

  3. C

    Exporting BigQuery results to a CSV file and importing it into Google Sheets

  4. D

    Connected Sheets

Xem giải thích

Đáp án

D — Connected Sheets.

Vì sao đúng

Yêu cầu là ngay trong Google Sheets, nối dữ liệu hạn mức trong Sheet với dữ liệu bán hàng trong BigQuery, và làm mới dễ dàng. Connected Sheets sinh ra cho đúng việc này.

⚠ Điểm mấu chốt — Sheets nói chuyện trực tiếp với BigQuery:

Google Sheets
        ↓
    Data → Data connectors → Connect to BigQuery
        ↓
    Chọn bảng company_sales.all_transactions
        ↓
    ⚠ Dữ liệu KHÔNG được tải hết vào Sheet
    → Sheet chỉ giữ một KẾT NỐI
    → mọi phép tính chạy Ở PHÍA BIGQUERY
        ↓
    → làm việc được với bảng HÀNG TỈ DÒNG
      trong một bảng tính

⚠ Vì sao "hàng tỉ dòng trong Sheets" là chuyện có thật:

Google Sheets giới hạn khoảng
    10 triệu ô
        ↓
    Nhập một bảng lớn → KHÔNG THỂ

Connected Sheets
        ↓
    Chỉ hiển thị PHẦN KẾT QUẢ
    (preview, pivot, biểu đồ, hàm)
        ↓
    Phép tính đẩy xuống BigQuery
        ↓
    → giới hạn ô không còn là vấn đề

⚠ Nối dữ liệu Sheet với dữ liệu BigQuery:

Sheet 1: hạn mức theo vùng (nhập tay)
Sheet 2: PIVOT TABLE từ Connected Sheets
         → doanh số thực tế theo vùng
        ↓
    Sheet 3: dùng VLOOKUP hoặc QUERY
             ghép hai bảng lại
        ↓
    → báo cáo so sánh hạn mức và thực tế
        ↓
    Bấm "Refresh" → số liệu mới nhất
    Hoặc đặt LỊCH làm mới tự động

Vì sao các phương án khác sai

  • C (xuất BigQuery ra CSV rồi nhập vào Sheets) — đây là phương án gần nhất về mặt "làm được", nhưng nó thủ công, không làm mới được, và giới hạn số ô của Sheets chặn ngay với dữ liệu lớn.

  • A (Looker) — nền tảng BI mạnh, nhưng đề nói rõ báo cáo phải nằm TRONG Google Sheets, và người dùng là nhà phân tích quen bảng tính.

  • B (Dataflow) — công cụ xử lý dữ liệu quy mô lớn, hoàn toàn quá tay và không tạo ra báo cáo trong Sheets.

Ghi nhớ

⚠ Connected Sheets — điều cần nhớ: | Điểm | Nội dung | |---|---| | Bản chất | Sheets nối THẲNG tới BigQuery | | Dữ liệu | KHÔNG tải hết vào Sheet — phép tính chạy ở BigQuery | | Công cụ dùng được | pivot table, biểu đồ, hàm, bộ lọc | | Làm mới | thủ công hoặc THEO LỊCH | | Quyền | người dùng cần quyền BigQuery của chính họ | | Chi phí | mỗi lần làm mới là một truy vấn tính tiền |

Từ khoá nhận diện:

"phân tích BigQuery ngay trong Google Sheets" → Connected Sheets "dashboard chia sẻ rộng" → Looker Studio "chỉ số thống nhất toàn công ty" → Looker "phân tích bằng Python" → Vertex AI Notebooks "xuất CSV rồi nhập tay" → hầu như luôn là phương án kém nhất

Vì sao Connected Sheets hợp với nhà phân tích nghiệp vụ Lý do
Không cần biết SQL pivot table và bộ lọc là đủ
Giao diện đã quen không phải học công cụ mới
Kết hợp dữ liệu tay và dữ liệu kho như hạn mức trong đề
Chia sẻ như Google Sheets thường
Có audit log biết ai truy cập dữ liệu gì
Kiểm soát chi phí khi dùng Connected Sheets Cách
Nối tới BẢNG TỔNG HỢP, không nối bảng thô giảm byte quét rất nhiều
Lọc theo cột phân vùng ngay trong kết nối
Đặt lịch làm mới hợp lý không cần mỗi giờ
maximum_bytes_billed ở cấp project trần an toàn
BI Engine tăng tốc và giảm chi phí truy vấn lặp
Cách nối dữ liệu tay với dữ liệu BigQuery Cách
VLOOKUP / XLOOKUP trong Sheet đơn giản nhất
Hàm QUERY() của Sheets linh hoạt hơn
Đưa bảng hạn mức LÊN BigQuery nối bằng SQL — bền hơn
Cách sau tốt hơn khi hạn mức cần dùng cho nhiều báo cáo
External table trỏ vào Sheet BigQuery đọc thẳng Google Sheet
External table trỏ vào Google Sheet Nội dung
BigQuery truy vấn thẳng một Sheet như bảng
Lợi ích quản lý viên vẫn sửa Sheet, SQL vẫn dùng số mới
Hạn chế chậm hơn bảng thường, không hợp dữ liệu lớn
Rất hợp với bảng tham chiếu nhỏ như hạn mức, danh mục
Kết hợp Connected Sheets + external table → hai chiều

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Kết nối trỏ vào bảng nào | menu Data → Data connectors trong Sheet | | Mỗi lần làm mới tốn bao nhiêu | INFORMATION_SCHEMA.JOBS trong BigQuery | | Ai xem được | quyền chia sẻ của Sheet và quyền BigQuery của từng người |

Và một lựa chọn kiến trúc đáng cân nhắc nếu bảng hạn mức được dùng ở nhiều báo cáo: đưa chính Sheet đó vào BigQuery làm external table. Quản lý viên vẫn cập nhật hạn mức trong Sheet như cũ, nhưng phép so sánh hạn mức với thực tế chuyển hẳn sang SQL — và mọi báo cáo khác đều dùng chung một nguồn thay vì mỗi người tự VLOOKUP một kiểu.

Câu 64 Data Pipeline Orchestration

A large Parquet file is uploaded to a Cloud Storage bucket at an unpredictable time each day. As soon as the file upload is complete, a complex Spark job must be triggered on an existing Dataproc cluster to process this file. The solution must be fully automated.

How should you design this event-driven workflow?

  1. A

    Create a Cloud Run Function with a Cloud Storage trigger that submits the job to the Dataproc API.

  2. B Manually monitor the bucket and start the Dataproc job from the Cloud Console.
  3. C Use Cloud Monitoring to create an alert that triggers the Dataproc job.
  4. D Use Cloud Scheduler to run the Dataproc job at a fixed time every night.
Xem giải thích

Đáp án

A — Tạo một Cloud Run function với trigger từ Cloud Storage, hàm này gọi Dataproc API để nộp job.

Vì sao đúng

Điểm quyết định của đề là tệp được tải lên vào một thời điểm KHÔNG ĐOÁN TRƯỚC ĐƯỢC mỗi ngày, và job phải chạy NGAY KHI tải lên xong. Chỉ kiến trúc hướng sự kiện đáp ứng được.

⚠ Điểm mấu chốt — sự kiện finalized báo tệp đã ghi XONG:

Tải tệp Parquet lên bucket
        ↓
    Cloud Storage phát sự kiện
    object.v1.FINALIZED
        ↓
    ⚠ "finalized" = ghi HOÀN TẤT,
      không phải "bắt đầu tải"
        ↓
    Cloud Run function được gọi
        ↓
    Hàm gọi Dataproc API nộp job
    lên cụm đang có
        ↓
    → tự động hoàn toàn, không có độ trễ chờ

⚠ Nội dung hàm — rất ngắn:

from google.cloud import dataproc_v1

def xu_ly(event, context):
    ten = event['name']
    if not ten.endswith('.parquet'):
        return                       # lọc theo đuôi
    client = dataproc_v1.JobControllerClient(...)
    client.submit_job(project_id=..., region='...',
        job={'placement': {'cluster_name': 'cum-cua-toi'},
             'spark_job': {...,
               'args': [f"gs://{event['bucket']}/{ten}"]}})
        ↓
    ⚠ Hàm chỉ NỘP job rồi trả về ngay
    → không chờ Spark chạy xong
    → tránh chạm giới hạn thời gian

⚠ Vì sao Cloud Scheduler không dùng được ở đây:

Cloud Scheduler chạy theo GIỜ CỐ ĐỊNH
        ↓
    Tệp tới lúc 2h → job chạy lúc 23h
    → trễ 21 giờ

    Tệp tới lúc 23h30 → job chạy lúc 23h
    → xử lý tệp của HÔM QUA
        ↓
    ⚠ Thời điểm không đoán trước
      → lịch cố định luôn sai

Xem thêm câu #12934 (cùng lô): cũng là tự động hoá, nhưng ở đó công việc chạy đúng 1 giờ sáng mỗi ngày → khoá là Cloud Scheduler. Hai khoá khác nhau vì một bên theo LỊCH, một bên theo SỰ KIỆN — hoàn toàn nhất quán.

Vì sao các phương án khác sai

  • D (Cloud Scheduler chạy job vào giờ cố định mỗi đêm) — đây là phương án gần nhất và tự động thật, nhưng không phản ứng theo sự kiện: có thể chạy khi tệp chưa tới, hoặc trễ nhiều giờ sau khi tệp đã tới.

  • C (Cloud Monitoring tạo cảnh báo để kích hoạt job) — Monitoring dùng cho chỉ số và cảnh báo vận hành, không phải cơ chế kích hoạt luồng dữ liệu; đường đi vòng và không đáng tin.

  • B (theo dõi thủ công rồi bấm chạy) — không tự động, trái yêu cầu.

Ghi nhớ

⚠ Lịch ↔ Sự kiện — bảng phải thuộc: | Kích hoạt theo | Khi nào dùng | Công cụ | |---|---|---| | LỊCH | thời điểm biết trước, đều đặn | Cloud Scheduler | | SỰ KIỆN | thời điểm KHÔNG đoán trước | Cloud Run function + trigger, Eventarc | | PHỤ THUỘC | nhiều bước nối nhau | Cloud Composer | | THỦ CÔNG | việc một lần | console, CLI | | Nhận diện | "không đoán trước được" → sự kiện |

Từ khoá nhận diện:

"ngay khi tệp được tải lên" → trigger Cloud Storage "đúng 1 giờ sáng mỗi ngày" → Cloud Scheduler "nhiều bước phụ thuộc nhau" → Cloud Composer "sự kiện từ nhiều dịch vụ GCP" → Eventarc "đợi cả một nhóm tệp tới đủ" → sensor trong Composer, hoặc tệp báo hiệu

Các sự kiện Cloud Storage Sự kiện
object.v1.finalized tệp ghi XONG — hay dùng nhất
object.v1.deleted tệp bị xoá
object.v1.archived phiên bản bị lưu trữ
object.v1.metadataUpdated metadata đổi
Lưu ý finalized cũng phát khi GHI ĐÈ
Không lọc được theo đuôi tệp ở trigger lọc trong mã
Ba cái bẫy của kiến trúc hướng sự kiện Bẫy
Sự kiện có thể tới NHIỀU LẦN xử lý phải bất biến
Hàm ghi lại vào chính bucket đó VÒNG LẶP VÔ TẬN
Nộp job trùng dùng job id cố định theo tên tệp
Nhiều tệp tới cùng lúc nhiều job cùng chạy — kiểm soát số lượng
Tệp tải lên nhiều phần finalized chỉ phát khi hoàn tất — an toàn
Nếu cần đợi NHIỀU tệp mới chạy Cách
Tệp báo hiệu (_SUCCESS) nguồn ghi tệp này khi đã xong hết
Trigger theo đúng tệp báo hiệu đó
Sensor trong Composer GCSObjectsWithPrefixExistenceSensor
Đếm tệp trong hàm trước khi nộp job
Vì sao cần xử lý khi mới có nửa dữ liệu là lỗi im lặng
Thay thế đáng cân nhắc Cách
Eventarc → Cloud Run linh hoạt hơn, nhiều nguồn sự kiện
Eventarc → Workflows có logic nhiều bước
Cloud Composer + sensor nếu đã có Composer cho luồng khác
Dataproc Serverless không cần cụm thường trực
Đề này cụm ĐÃ CÓ SẴN → chỉ cần nộp job

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Hàm có được gọi không | Logs Explorer, lọc theo tên hàm | | Job đã nộp chưa | gcloud dataproc jobs list --region=<r> | | Có nộp trùng không | đếm số job cho cùng một tệp |

Và một chi tiết nên xử lý ngay trong hàm ngay từ phiên bản đầu: đặt job id suy ra từ tên tệp. Sự kiện Cloud Storage có thể được phát lại, và một job Spark nặng chạy hai lần trên cùng một tệp vừa tốn tiền vừa có thể sinh dữ liệu trùng ở đầu ra — một job id cố định khiến lần nộp thứ hai bị từ chối thay vì âm thầm chạy song song.

Câu 65 Data Management

A Cloud Run Function needs to be able to write records into a BigQuery table named processed_logs in the logs_dataset. You have already enabled the BigQuery API for the project.

Following the principle of least privilege, which IAM role should you grant to the Cloud Run Function's service account to give it the necessary permissions and nothing more?

  1. A BigQuery Data Editor (roles/bigquery.dataEditor) on the dataset
  2. B BigQuery Job User (roles/bigquery.jobUser) on the project
  3. C BigQuery Data Owner (roles/bigquery.dataOwner) on the dataset
  4. D BigQuery Admin (roles/bigquery.admin)
Xem giải thích

Đáp án

A — BigQuery Data Editor (roles/bigquery.dataEditor) trên DATASET.

Vì sao đúng

Service account chỉ cần GHI bản ghi vào một bảng trong logs_dataset. dataEditor cho đúng quyền đó, và cấp trên dataset thay vì trên project là mức hẹp nhất phù hợp.

⚠ Điểm mấu chốt — dataEditor cho đúng thứ cần:

roles/bigquery.dataEditor
        ↓
    CÓ:
      bigquery.tables.updateData   ← GHI dữ liệu
      bigquery.tables.getData      ← đọc
      bigquery.tables.create/update/delete
      bigquery.tables.list
        ↓
    KHÔNG CÓ:
      quản lý QUYỀN của dataset
      động tới dataset khác

⚠ Vì sao cấp trên DATASET, không cấp trên project:

Cấp trên project
        ↓
    → ghi được vào MỌI dataset
    → kể cả những cái không liên quan

Cấp trên logs_dataset
        ↓
    → chỉ ghi được vào đúng nơi cần
        ↓
    ⚠ Cùng một vai trò, khác phạm vi
      = khác biệt rất lớn về rủi ro

⚠ Một điểm quan trọng về jobUser:

Ghi bằng STORAGE WRITE API hoặc
streaming insert
        ↓
    → KHÔNG tạo job
    → chỉ cần dataEditor
        ↓
Ghi bằng LOAD JOB hoặc INSERT bằng SQL
        ↓
    → CÓ tạo job
    → cần thêm roles/bigquery.jobUser
        ↓
    ⚠ Đề chỉ nói "ghi bản ghi vào bảng"
      và hỏi MỘT vai trò
      → dataEditor là đáp án

Xem thêm câu #12957 (cùng lô): ở đó nhà phân tích CHẠY TRUY VẤN nên cần dataViewer + jobUser. Câu này là service account GHI dữ liệu → dataEditor. Hai khoá khác nhau vì hành động khác nhau, nhất quán với nhau.

Vì sao các phương án khác sai

  • C (BigQuery Data Owner trên dataset) — đây là phương án gần nhất và ghi được, nhưng nó thêm quyền quản lý IAM của dataset — rộng hơn mức cần.

  • B (BigQuery Job User trên project) — cho phép chạy job nhưng không đọc ghi được bảng nào; một mình nó không đủ.

  • D (BigQuery Admin) — toàn quyền BigQuery trên toàn project, rộng hơn hẳn.

Ghi nhớ

⚠ Vai trò BigQuery theo hành động — bảng phải thuộc: | Hành động | Vai trò | |---|---| | Chỉ đọc dữ liệu | bigquery.dataViewer | | GHI dữ liệu vào bảng | bigquery.dataEditor | | Quản lý quyền của dataset | bigquery.dataOwner | | Chạy job (truy vấn, nạp, xuất) | bigquery.jobUser | | Chạy job + tạo dataset riêng | bigquery.user | | Toàn quyền | bigquery.admin | | Chỉ xem lược đồ | bigquery.metadataViewer |

Từ khoá nhận diện:

"ứng dụng GHI dữ liệu vào bảng" → dataEditor trên dataset "nhà phân tích chạy SELECT" → dataViewer + jobUser "quản lý ai được vào dataset" → dataOwner "cấp ở project cho nhanh" → thường là phương án SAI "Admin" → gần như luôn quá rộng trong câu hỏi quyền tối thiểu

Các cách ghi vào BigQuery và quyền tương ứng Cách
Storage Write API dataEditor — khuyến nghị cho ứng dụng
tabledata.insertAll (streaming cũ) dataEditor
Load job từ GCS dataEditor + jobUser + storage.objectViewer
INSERT bằng SQL dataEditor + jobUser
Với Cloud Run function ghi log Storage Write API là lựa chọn tốt nhất
Quyền tối thiểu cho service account Nguyên tắc
Một service account cho MỖI ứng dụng không dùng chung
KHÔNG dùng service account MẶC ĐỊNH nó có roles/editor
Cấp ở mức tài nguyên hẹp nhất dataset, không phải project
Không tạo khoá JSON dùng danh tính gắn sẵn của Cloud Run
Rà soát bằng Recommender hạ vai trò không dùng tới
Vì sao service account mặc định lại nguy hiểm Nội dung
Compute Engine default SA có roles/editor trên cả project
Nghĩa là sửa và xoá gần như mọi thứ
Kẻ chiếm được ứng dụng chiếm luôn quyền đó
Chặn bằng Organization Policy automaticIamGrantsForDefaultServiceAccounts
Thay thế service account riêng cho từng dịch vụ
Gán service account cho Cloud Run function Cách
Khi triển khai --service-account=sa@du-an.iam.gserviceaccount.com
Người triển khai cần roles/iam.serviceAccountUser trên SA đó
Trong mã thư viện tự lấy token — không cần khoá
Kiểm tra log của hàm ghi rõ danh tính đang dùng
Sai lầm để mặc định rồi cấp quyền cho SA mặc định

Ba việc kiểm chứng: | Việc | Cách | |---|---| | SA có quyền gì trên dataset | bq show --format=prettyjson logs_dataset → access | | Hàm chạy dưới danh nghĩa ai | gcloud functions describe <ten> --gen2 → serviceAccountEmail | | Vì sao bị từ chối | Policy Troubleshooter |

Và một thói quen đáng có với mọi dịch vụ mới triển khai: tạo service account riêng ngay từ đầu, kể cả khi thấy phiền. Dùng tạm tài khoản mặc định "để chạy được đã" là quyết định gần như không bao giờ được quay lại sửa — và nó lặng lẽ cấp cho một hàm ghi log quyền sửa đổi gần như toàn bộ project.

Câu 66 Data Analysis and Presentation

A large enterprise is choosing a BI platform. Their key requirements include: a centrally governed, version-controlled semantic layer to define business metrics consistently, the ability to integrate with third-party applications via a robust API, and granular, row-level security to ensure users only see the data they are authorized to see.

Which Google Cloud analytics tool is designed to meet these advanced, enterprise-grade requirements?

  1. A BigQuery Geo Viz
  2. B Looker Studio
  3. C Looker
  4. D Vertex AI Notebooks
Xem giải thích

Đáp án

C — Looker.

Vì sao đúng

Đề liệt kê ba yêu cầu, và cả ba đều là những thứ Looker có mà Looker Studio không có: lớp ngữ nghĩa được quản trị tập trung, có quản lý phiên bản, API mạnh để tích hợp, và bảo mật ở cấp DÒNG rất chi tiết.

⚠ Điểm mấu chốt — ba yêu cầu ánh xạ vào ba tính năng:

"lớp ngữ nghĩa quản trị tập trung,
 có quản lý phiên bản"
        ↓
    LOOKML — lưu trong Git,
    review được, có môi trường dev/prod

"API mạnh để tích hợp ứng dụng bên thứ ba"
        ↓
    LOOKER API — quản lý mọi thứ bằng mã,
    nhúng dashboard, chạy truy vấn

"bảo mật cấp dòng chi tiết"
        ↓
    USER ATTRIBUTES + ACCESS_FILTER
    trong chính mô hình LookML

⚠ Bảo mật cấp dòng của Looker khai ngay trong mô hình:

explore: don_hang {
  access_filter: {
    field: don_hang.khu_vuc
    user_attribute: khu_vuc_cua_nguoi_dung
  }
}
        ↓
    Mỗi người dùng có thuộc tính "khu_vuc"
        ↓
    → Looker TỰ THÊM điều kiện lọc
      vào mọi truy vấn của họ
        ↓
    ⚠ Áp cho MỌI dashboard, MỌI Look
    → không phải nhớ lọc ở từng báo cáo

⚠ Vì sao Looker Studio không đáp ứng được:

Looker Studio
        ↓
    - KHÔNG có lớp mô hình tập trung
    - KHÔNG có quản lý phiên bản
    - Lọc dòng phải làm THỦ CÔNG
      ở từng báo cáo, hoặc dựa vào
      row-level security của BigQuery
    - API hạn chế hơn nhiều
        ↓
    → hợp với báo cáo nhanh,
      không hợp với yêu cầu doanh nghiệp

Xem thêm câu #12946 (cùng lô): cũng khoá Looker, cũng vì LookML. Hai câu nhất quán, nhấn mạnh hai khía cạnh khác nhau của cùng một lý do. Và #12947 (cùng lô) khoá Looker Studio vì yêu cầu ở đó là miễn phí và đơn giản — khác hoàn toàn.

Vì sao các phương án khác sai

  • B (Looker Studio) — đây là phương án gần nhất về tên gọi và cũng là công cụ BI, nhưng không có lớp ngữ nghĩa quản trị tập trung, không có quản lý phiên bản, và API hạn chế.

  • D (Vertex AI Notebooks) — môi trường phân tích bằng mã, ngược hoàn toàn với yêu cầu nhất quán và quản trị.

  • A (BigQuery Geo Viz) — công cụ nhỏ để vẽ dữ liệu địa lý lên bản đồ, không phải nền tảng BI.

Ghi nhớ

⚠ Looker ↔ Looker Studio cho doanh nghiệp — bảng phải thuộc: | Yêu cầu | Looker | Looker Studio | |---|---|---| | Lớp ngữ nghĩa tập trung | LookML | không có | | Quản lý phiên bản | Git | không | | Row-level security | access_filter + user attribute | dựa vào nguồn dữ liệu | | API | mạnh, đầy đủ | hạn chế | | Nhúng | signed embed, đa khách hàng | nhúng cơ bản | | Chi phí | có phí | bản cơ bản miễn phí |

Từ khoá nhận diện:

"lớp ngữ nghĩa, quản trị, phiên bản, API, row-level" → Looker "dashboard nhanh, miễn phí" → Looker Studio "bản đồ từ truy vấn BigQuery" → BigQuery Geo Viz "phân tích bằng Python" → Vertex AI Notebooks "bảng tính" → Connected Sheets

Các thành phần bảo mật của Looker Thành phần
User attribute thuộc tính gắn với người dùng: khu vực, khách hàng, phòng ban
access_filter lọc dòng theo user attribute
access_grant ẩn/hiện trường, explore theo quyền
Model set / permission set nhóm quyền theo vai trò
Kết nối dùng user attribute mỗi người dùng danh tính riêng xuống kho
Ưu điểm khai một lần trong mô hình, áp mọi nơi
Looker API dùng để làm gì Việc
Nhúng dashboard có chữ ký signed embed URL
Chạy Look và lấy kết quả đưa vào ứng dụng
Quản lý người dùng và quyền tự động hoá
Lên lịch gửi báo cáo
CI/CD cho LookML kiểm thử và triển khai mô hình
SDK Python, TypeScript, Java, Ruby...
LookML — vòng đời phát triển Bước
1 Viết mô hình trong development mode
2 LookML Validator kiểm tra cú pháp
3 Content validator kiểm nội dung bị hỏng
4 Pull request trên Git, đồng nghiệp review
5 Deploy to production
Lợi ích thay đổi chỉ số phải qua review — không ai tự sửa lén
Khi nào doanh nghiệp thật sự cần Looker Dấu hiệu
Cùng một chỉ số ra nhiều con số khác nhau
Cần nhúng vào sản phẩm bán cho khách
Cần phân quyền theo dòng phức tạp
Cần kiểm toán ai đổi định nghĩa gì
Nếu chưa có dấu hiệu nào Looker Studio rẻ hơn và đủ dùng

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Chỉ số định nghĩa ở đâu | tìm measure trong kho LookML | | Ai thấy được dòng nào | kiểm tra user attribute của người đó | | Ai đổi mô hình gần đây | lịch sử Git của dự án LookML |

Và một điều nên tính vào chi phí ngay từ khi chọn Looker: cần người bảo trì LookML. Lớp ngữ nghĩa mang lại sự nhất quán, nhưng nó là mã — cần người review pull request, quản lý môi trường và cập nhật khi mô hình dữ liệu đổi. Đó là cái giá hợp lý cho doanh nghiệp lớn, và là gánh nặng không cần thiết cho một đội năm người.

Câu 67 Data Management

The data engineering team's critical workflows are orchestrated using Cloud Composer in the us-central1 region. The company's business continuity plan requires a disaster recovery strategy that allows pipeline orchestration to resume in a different region (us-east1) within hours if a full regional outage occurs.

What is the most effective DR strategy for Cloud Composer?

  1. A Regularly back up the environment's DAGs, data, and configuration to a multi-regional Cloud Storage bucket and be prepared to redeploy.
  2. B Increase the number of schedulers and workers in the existing environment.
  3. C Enable high availability on the Cloud Composer environment.
  4. D Take a daily snapshot of the entire Cloud Composer environment.
Xem giải thích

Đáp án

A — Thường xuyên sao lưu DAG, dữ liệu và cấu hình của môi trường sang bucket Cloud Storage đa vùng, và sẵn sàng triển khai lại.

Vì sao đúng

Môi trường Cloud Composer gắn với MỘT Region và không tự chuyển sang Region khác được. Vì vậy chiến lược khôi phục thảm hoạ phải là giữ đủ nguyên liệu để DỰNG LẠI môi trường ở Region khác.

⚠ Điểm mấu chốt — cần sao lưu ba thứ:

1. DAG
    → nằm trong bucket của môi trường,
      thư mục /dags
    → nên là NGUỒN TỪ GIT chứ không phải
      chỉ có bản trong bucket

2. CẤU HÌNH môi trường
    → biến Airflow, connection,
      gói Python cài thêm,
      cấu hình môi trường (kích thước, phiên bản)

3. DỮ LIỆU phụ trợ
    → /data, /plugins trong bucket

⚠ Vì sao mục tiêu "trong vòng vài giờ" là hợp lý:

Tạo mới một môi trường Composer
        ↓
    Mất khoảng 20–30 PHÚT
        ↓
    + Chép DAG và cấu hình vào
    + Nhập lại biến và connection
    + Kiểm tra kết nối tới các dịch vụ
        ↓
    → tổng cộng VÀI GIỜ
        ↓
    ⚠ Đúng bằng RTO mà đề nêu

⚠ Vì sao HA của Composer không giải quyết được:

Bật HA cho môi trường Composer
        ↓
    → nhiều scheduler, nhiều zone
      TRONG CÙNG MỘT REGION
        ↓
    ⚠ Chống được hỏng một ZONE
    ⚠ KHÔNG chống được mất CẢ REGION
        ↓
    → giống hệt trường hợp Cloud SQL:
      HA là chuyện trong Region,
      DR là chuyện giữa các Region

⚠ Cách làm cho việc dựng lại thật sự nhanh:

- DAG lưu trong GIT, đồng bộ vào bucket
  bằng CI/CD → dựng lại chỉ là chạy pipeline
- Môi trường khai bằng TERRAFORM
  → terraform apply với region khác
- Biến và connection lưu trong
  SECRET MANAGER, không gõ tay
- ⚠ DIỄN TẬP định kỳ

Vì sao các phương án khác sai

  • D (chụp snapshot môi trường hằng ngày) — đây là phương án gần nhất và Composer 2 thật sự có tính năng snapshot, hữu ích cho việc sao lưu và di chuyển. Nhưng snapshot khôi phục vào môi trường cùng phiên bản và bản thân nó không phải chiến lược DR đa Region hoàn chỉnh — vẫn cần bản sao ở nơi khác và quy trình dựng lại. Phương án A mô tả đúng chiến lược đầy đủ.

  • C (bật HA cho môi trường) — chống được hỏng zone, không chống được mất Region.

  • B (tăng số scheduler và worker) — cải thiện hiệu năng và khả năng chịu tải, không liên quan tới khôi phục thảm hoạ.

Ghi nhớ

⚠ HA ↔ DR — bảng phải thuộc: | | HA (sẵn sàng cao) | DR (khôi phục thảm hoạ) | |---|---|---| | Chống | hỏng ZONE, hỏng thành phần | mất CẢ REGION | | Phạm vi | trong một Region | giữa các Region | | Thời gian phục hồi | tự động, vài giây tới phút | thủ công, vài giờ | | Composer | nhiều scheduler, nhiều zone | dựng lại ở Region khác | | Ghi nhớ | HA không thay thế DR |

Từ khoá nhận diện:

"mất cả Region, khôi phục trong vài giờ" → DR, dựng lại từ bản sao "chịu được hỏng một zone" → HA "RPO / RTO" → luôn là câu hỏi về DR "snapshot môi trường Composer" → công cụ hỗ trợ, không phải cả chiến lược "tăng worker" → hiệu năng, không phải DR

Những gì phải giữ để dựng lại Composer Thành phần
DAG nên là Git, không chỉ bucket
Biến Airflow xuất ra JSON, hoặc Secret Manager
Connection Secret Manager
Gói Python cài thêm requirements.txt trong Git
Cấu hình môi trường Terraform
Dữ liệu trong /data, /plugins đồng bộ sang bucket đa vùng
Cloud Composer snapshot — dùng thế nào Nội dung
Việc chụp trạng thái môi trường: DAG, biến, connection, metadata
Lệnh gcloud composer environments snapshots save/load
Dùng cho di chuyển, nâng cấp, sao lưu
Hạn chế môi trường đích phải tương thích
Trong DR nên có, kết hợp với bản sao ở Region khác
Xây môi trường Composer "dựng lại được" Thói quen
DAG chỉ đến từ Git qua CI/CD không ai sửa trực tiếp trong bucket
Hạ tầng khai bằng Terraform đổi Region là đổi một biến
Bí mật trong Secret Manager không nằm trong môi trường
DAG BẤT BIẾN chạy lại an toàn sau sự cố
Tài liệu quy trình DR ai làm gì, theo thứ tự nào
RPO và RTO cho lớp điều phối Nội dung
RPO mất bao nhiêu LỊCH SỬ chạy — thường chấp nhận được
RTO bao lâu thì luồng chạy lại — đề nêu "vài giờ"
Điểm may mắn Composer không giữ dữ liệu nghiệp vụ
Nghĩa là mất môi trường ≠ mất dữ liệu
Ưu tiên khi khôi phục chạy lại luồng, không phải cứu metadata Airflow

Ba việc kiểm chứng: | Việc | Cách | |---|---| | DAG có trong Git không | kiểm tra kho mã, không chỉ bucket | | Biến và connection lưu ở đâu | Secret Manager, hoặc bản xuất định kỳ | | Dựng lại mất bao lâu thật | DIỄN TẬP một lần và bấm giờ |

Và điểm may mắn nên nói rõ khi bàn về DR cho Cloud Composer: nó không giữ dữ liệu nghiệp vụ nào cả. Mất môi trường nghĩa là mất lớp điều phối và lịch sử chạy, còn dữ liệu vẫn nằm nguyên trong BigQuery và Cloud Storage — nên mục tiêu khôi phục chỉ là làm cho các luồng chạy lại, và đó là mục tiêu dễ đạt hơn nhiều so với khôi phục một cơ sở dữ liệu.

Câu 68 Data Analysis and Presentation

Your company has an external-facing SaaS application and wants to embed dashboards within the application's UI. It is critical that each customer who logs in can only see the data that belongs to them. The solution must provide robust security for this multi-tenant scenario and have a strong API for embedding.

Furthermore, the authentication is handled entirely by the SaaS application, and the BI tool must be able to programmatically generate secure, temporary embed URLs for users who do not have Google accounts.

Which BI tool and methodology is specifically designed for this advanced embedded analytics and programmatic row-level security use case?

  1. A

    BigQuery ML, by creating a trained model for each customer and exposing predictions through an API, which are then visualized in the application's custom UI.

  2. B

    Looker Studio, by enabling viewer-level credentials and instructing the SaaS application to pass the logged-in user's email as a filter parameter in the embed URL.

  3. C

    Looker, by using its API to generate a secure signed embed URL that includes user attributes (like customer_id), which are then used by an access_filter in the LookML model to enforce row-level security.

  4. D

    Looker Studio Pro, by connecting to the data using a service account and creating a separate dashboard version for each customer, embedding the specific URL for each one.

Xem giải thích

Đáp án

C — Looker, dùng API sinh signed embed URL có kèm user attribute (như customer_id), rồi access_filter trong mô hình LookML dùng thuộc tính đó để lọc dữ liệu.

Vì sao đúng

Đề nêu bốn ràng buộc, và chỉ Looker đáp ứng đủ: nhúng vào ứng dụng SaaS, cách ly dữ liệu giữa các khách hàng, xác thực do ứng dụng SaaS lo, và người xem KHÔNG có tài khoản Google.

⚠ Điểm mấu chốt — signed embed giải quyết bài toán "không có tài khoản Google":

Người dùng đăng nhập vào ứng dụng SaaS
        ↓
    Ứng dụng biết họ là khách hàng nào
        ↓
    Ứng dụng SINH signed embed URL:
      - ký bằng embed secret của Looker
      - nhúng USER ATTRIBUTES,
        ví dụ customer_id = "KH123"
      - có thời hạn
        ↓
    ⚠ Looker TIN chữ ký đó
    → không cần người dùng có tài khoản Google
    → không cần tài khoản Looker riêng

⚠ Và access_filter biến thuộc tính đó thành bộ lọc:

explore: du_lieu_khach_hang {
  access_filter: {
    field: du_lieu_khach_hang.customer_id
    user_attribute: customer_id
  }
}
        ↓
    Mọi truy vấn của phiên nhúng đó
    TỰ ĐỘNG kèm điều kiện
      customer_id = 'KH123'
        ↓
    ⚠ Lọc áp ở TẦNG MÔ HÌNH,
      không phải ở URL hay ở giao diện
    → khách hàng KHÔNG thể sửa URL
      để xem dữ liệu của người khác

⚠ Vì sao "lọc bằng tham số trên URL" là lỗ hổng:

Nhúng kèm ?filter=customer_id=KH123
        ↓
    ⚠ Người dùng SỬA URL thành KH124
        ↓
    → xem được dữ liệu khách hàng khác
        ↓
    ⚠ Đây chính là điểm yếu của
      phương án Looker Studio trong đề
    → bộ lọc trên URL KHÔNG PHẢI
      cơ chế bảo mật

Xem thêm câu #12946 và #12976 (cùng lô): cùng khoá Looker, vì LookML và vì quản trị doanh nghiệp. Ba câu nhất quán — câu này nhấn mạnh nhúng và đa khách hàng.

Vì sao các phương án khác sai

  • B (Looker Studio, truyền email người dùng làm tham số lọc trên URL) — đây là phương án gần nhất và trông có vẻ chạy được, nhưng tham số trên URL sửa được, nên không phải cơ chế bảo mật; hơn nữa Looker Studio cần người xem có tài khoản Google.

  • D (Looker Studio Pro, mỗi khách hàng một dashboard riêng) — không mở rộng nổi: hàng trăm khách hàng là hàng trăm dashboard phải bảo trì, và vẫn không giải quyết được vấn đề tài khoản.

  • A (BigQuery ML, mỗi khách hàng một mô hình) — hoàn toàn lạc đề: đây là bài toán hiển thị và phân quyền, không phải học máy.

Ghi nhớ

⚠ Bốn cách nhúng của Looker — bảng phải thuộc: | Cách | Dùng khi | |---|---| | Signed embed (SSO embed) | nhúng cho người dùng KHÔNG có tài khoản Looker | | Private embed | người xem đã đăng nhập Looker | | Public embed | dữ liệu công khai — cẩn thận | | API + giao diện tự dựng | toàn quyền kiểm soát hiển thị | | Với SaaS đa khách hàng | signed embed là lựa chọn duy nhất hợp lý |

Từ khoá nhận diện:

"nhúng vào SaaS, người xem không có tài khoản Google" → Looker signed embed "mỗi khách chỉ thấy dữ liệu của mình" → user attribute + access_filter "lọc bằng tham số URL" → KHÔNG phải cơ chế bảo mật "dashboard nội bộ, có tài khoản Google" → Looker Studio "lọc dòng ngay trong BigQuery" → row-level security

Signed embed hoạt động thế nào Bước
1 Ứng dụng xác thực người dùng theo cách của nó
2 Ứng dụng dựng URL kèm external_user_id, user attributes, permissions, models
3 Ký bằng embed secret (HMAC)
4 Trình duyệt mở URL trong iframe
5 Looker xác minh chữ ký, tạo phiên tạm
⚠ Embed secret KHÔNG BAO GIỜ để lộ ra client
Bảo mật cho kịch bản đa khách hàng Lớp
access_filter theo user attribute lọc dòng ở tầng mô hình
access_grant ẩn trường, ẩn explore
Permission set hẹp chỉ xem, không khám phá
Model set giới hạn mô hình truy cập được
Ký ở phía MÁY CHỦ không bao giờ ở trình duyệt
URL có hạn dùng phiên hết hạn
Sai lầm kinh điển khi làm đa khách hàng Sai lầm
Lọc ở tầng giao diện hoặc URL sửa được
Một dashboard cho mỗi khách hàng không mở rộng nổi
Để embed secret ở phía client lộ là mất tất cả
Tin vào tham số client gửi lên phải ký từ máy chủ
Không kiểm thử chéo luôn thử đăng nhập khách A xem có thấy dữ liệu khách B
Ba tầng có thể lọc dòng Tầng
Looker access_filter ở tầng BI — như đề này
BigQuery row-level security ở tầng kho — áp cho mọi công cụ
Bảng riêng cho từng khách hàng cách ly cứng nhất, khó mở rộng
Kết hợp hai tầng đầu cùng lúc cho hệ thống quan trọng
Nguyên tắc phòng thủ nhiều lớp

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Bộ lọc có thật sự áp không | xem SQL Looker sinh ra trong tab SQL | | Khách A có thấy dữ liệu khách B không | thử nghiệm chéo, bắt buộc | | Embed secret có bị lộ không | rà soát mã phía client và kho mã |

Và một phép kiểm thử phải làm trước mỗi lần phát hành trong kịch bản đa khách hàng: đăng nhập bằng danh tính của khách hàng A rồi tìm mọi cách để nhìn thấy dữ liệu của khách hàng B. Sửa tham số URL, đổi bộ lọc trong giao diện, tải kết quả về — nếu lớp access_filter được cấu hình đúng, mọi cách đều thất bại; và đó là thứ duy nhất chứng minh được rằng nó đúng.

Câu 69 Data Analysis and Presentation

An analyst is running queries against a 10 TB sales_events table in BigQuery. The queries are slow and costly because they almost always include WHERE event_date > 'YYYY-MM-DD' to analyze recent data.

What change should you make to the table to significantly improve the performance and reduce the cost of these queries?

  1. A Recreate the table and cluster it by the event_date column.
  2. B Purchase more BigQuery slots for the project.
  3. C Recreate the table and partition it by the event_date column.
  4. D Export the table to Cloud Storage and use BigQuery federated queries.
Xem giải thích

Đáp án

C — Tạo lại bảng với PHÂN VÙNG (partition) theo cột event_date.

Vì sao đúng

Truy vấn gần như luôn lọc theo event_date, và phân vùng cho phép BigQuery bỏ qua hoàn toàn những phân vùng không thoả điều kiện — giảm cả thời gian lẫn chi phí.

⚠ Điểm mấu chốt — partition pruning:

Bảng 10 TB, phân vùng theo ngày
        ↓
    WHERE event_date > '2026-08-01'
        ↓
    BigQuery đọc SIÊU DỮ LIỆU phân vùng
        ↓
    → chỉ QUÉT các phân vùng thoả điều kiện
    → 30 ngày gần nhất thay vì 3 năm
        ↓
    ⚠ Quét ~1% dữ liệu
    → nhanh hơn và RẺ HƠN khoảng 100 lần

⚠ ⚠ Phân vùng ↔ phân cụm — phải phân biệt dứt điểm:

PARTITIONING (phân vùng)
        ↓
    CHIA VẬT LÝ bảng thành các phần
    theo NGÀY, số nguyên, hoặc thời điểm nạp
        ↓
    → BỎ QUA HẲN phân vùng không cần
    → chi phí GIẢM MẠNH và ĐOÁN TRƯỚC ĐƯỢC
    → tối đa 4.000 phân vùng

CLUSTERING (phân cụm)
        ↓
    SẮP XẾP dữ liệu TRONG mỗi phân vùng
    theo tối đa 4 cột
        ↓
    → bỏ qua các khối không liên quan
    → mức giảm KHÔNG đoán trước được
    → chi phí ước tính trước không phản ánh

⚠ Vì sao chỉ phân cụm theo event_date là chưa tối ưu:

Cluster theo event_date
        ↓
    → CÓ giúp, nhưng ít hơn hẳn
    → không loại bỏ dữ liệu ở mức phân vùng
    → BigQuery không báo trước
      chi phí sẽ giảm bao nhiêu
        ↓
    Với cột NGÀY dùng để lọc thường xuyên,
    PHÂN VÙNG luôn là lựa chọn đúng
        ↓
    Tốt nhất: PHÂN VÙNG theo ngày
              + PHÂN CỤM theo cột lọc khác

⚠ Tạo lại bảng có phân vùng:

CREATE TABLE `du_an.sales_events_moi`
PARTITION BY DATE(event_date)
CLUSTER BY khu_vuc, san_pham
OPTIONS(
  require_partition_filter = TRUE
) AS
SELECT * FROM `du_an.sales_events`;
        ↓
    ⚠ require_partition_filter = TRUE
    → BẮT BUỘC mọi truy vấn phải lọc
      theo cột phân vùng
    → chặn hẳn những câu SELECT quét cả bảng

Vì sao các phương án khác sai

  • A (tạo lại bảng và PHÂN CỤM theo event_date) — đây là phương án gần nhất và có giúp một phần, nhưng phân cụm chỉ sắp xếp dữ liệu; nó không cắt bỏ hẳn phần dữ liệu như phân vùng, và mức giảm chi phí không đoán trước được.

  • B (mua thêm slot) — có thể làm truy vấn nhanh hơn, nhưng vẫn quét đúng lượng dữ liệu đó — không giải quyết gốc rễ và thường tốn hơn.

  • D (xuất ra Cloud Storage rồi dùng federated query) — chậm hơn hẳn và mất các tính năng tối ưu của bảng gốc.

Ghi nhớ

⚠ Phân vùng ↔ phân cụm — bảng phải thuộc: | | Partitioning | Clustering | |---|---|---| | Cơ chế | chia bảng thành các phần vật lý | sắp xếp trong phân vùng | | Số cột | MỘT | tối đa 4, có thứ tự | | Kiểu cột | DATE, TIMESTAMP, DATETIME, INT64 | hầu hết kiểu | | Giảm chi phí | mạnh và ĐOÁN TRƯỚC ĐƯỢC | không đoán trước được | | Giới hạn | 4.000 phân vùng | không | | Dùng chung | nên dùng CẢ HAI |

Từ khoá nhận diện:

"luôn lọc theo NGÀY" → phân vùng theo ngày "lọc theo nhiều cột khác nhau" → phân cụm "bảng nhỏ hơn 1 GB" → phân cụm thôi, phân vùng không lợi "quá 4.000 phân vùng" → phân vùng theo THÁNG, hoặc phân cụm "truy vấn chậm nhưng quét ít" → mới cần nghĩ tới slot

Ba loại phân vùng của BigQuery Loại
Theo CỘT thời gian PARTITION BY DATE(event_date) — như đề này
Theo THỜI ĐIỂM NẠP _PARTITIONTIME — khi không có cột ngày
Theo DẢI SỐ NGUYÊN RANGE_BUCKET
Mức chia ngày, giờ, tháng, năm
Chọn giờ khi dữ liệu rất lớn mỗi ngày và hay lọc theo giờ
Các lợi ích khác của phân vùng Lợi ích
Long-term storage tính theo TỪNG phân vùng phân vùng cũ tự giảm ~50% giá
Đặt hạn dùng theo phân vùng tự xoá dữ liệu cũ
Ghi đè một phân vùng nạp lại một ngày mà không đụng ngày khác
require_partition_filter chặn truy vấn quét cả bảng
Xoá dữ liệu cũ DELETE theo phân vùng rẻ hơn nhiều
Bẫy khiến phân vùng MẤT tác dụng Bẫy
Bọc cột phân vùng trong hàm WHERE DATE(ts) = ... có thể không cắt được
So sánh với giá trị không tĩnh subquery làm BigQuery không cắt trước được
Lọc theo cột KHÁC không liên quan tới phân vùng
JOIN rồi mới lọc lọc trước khi join
Cách kiểm --dry_run — số byte có giảm không
Quy trình chuyển bảng sang có phân vùng Bước
1 CREATE TABLE ... PARTITION BY ... AS SELECT * FROM cũ
2 Đối chiếu số dòng hai bảng
3 Cập nhật pipeline ghi vào bảng mới
4 Đổi tên hoặc tạo view trỏ sang bảng mới
5 Xoá bảng cũ sau khi yên tâm
Lưu ý không đổi bảng đang có thành bảng phân vùng tại chỗ

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Bảng có phân vùng chưa | bq show <dataset>.<bảng> → Time Partitioning | | Truy vấn có cắt được không | --dry_run — so số byte trước và sau | | Phân vùng nào lớn nhất | truy vấn INFORMATION_SCHEMA.PARTITIONS |

Và một tuỳ chọn rất đáng bật cùng lúc với việc phân vùng: require_partition_filter = TRUE. Nó buộc mọi truy vấn phải kèm điều kiện lọc theo cột phân vùng, và biến một câu SELECT * gõ vội trên bảng 10 TB từ một hoá đơn bất ngờ thành một thông báo lỗi vô hại.

Câu 70 Data Management

A data governance team needs to provide analysts with governed, in-place access to a data lake of Parquet files in Google Cloud Storage. The data contains sensitive PII (Personally Identifiable Information) in several columns. The requirement is to allow querying through BigQuery while implementing centralized, column-level masking for the sensitive data.

Which combination of table type and security control is designed for this purpose?

  1. A

    BigLake tables with policy tags

  2. B

    Regular external tables with an authorized view

  3. C

    Datastream with real-time transformations

  4. D

    BigQuery managed tables with IAM (Identity and Access Management) permissions

Xem giải thích

Đáp án

A — BigLake table kết hợp với policy tag.

Vì sao đúng

Đề nêu ba yêu cầu: truy cập TẠI CHỖ các tệp Parquet trong Cloud Storage, truy vấn qua BigQuery, và che dữ liệu nhạy cảm ở cấp CỘT một cách TẬP TRUNG. Chỉ BigLake làm được cả ba.

⚠ Điểm mấu chốt — BigLake là bảng ngoài CÓ kiểm soát chi tiết:

EXTERNAL TABLE thường
        ↓
    BigQuery đọc tệp trong GCS
        ↓
    ⚠ Người dùng phải có quyền TRÊN CHÍNH BUCKET
    ⚠ KHÔNG hỗ trợ column-level security
    ⚠ KHÔNG hỗ trợ row-level security
        ↓
    → ai truy vấn được cũng đọc thẳng
      tệp gốc được

BIGLAKE TABLE                     ← đề này
        ↓
    Truy cập qua CONNECTION có
    service account riêng
        ↓
    ⚠ Người dùng KHÔNG cần quyền trên bucket
    ⚠ CÓ column-level security (policy tag)
    ⚠ CÓ row-level security
    ⚠ CÓ dynamic data masking
        ↓
    → BigQuery trở thành CỬA DUY NHẤT
      vào data lake

⚠ Cách dựng:

-- 1. Tạo connection (service account của BigQuery)
--    cấp cho SA đó roles/storage.objectViewer trên bucket

-- 2. Tạo BigLake table
CREATE EXTERNAL TABLE `du_an.ho_du_lieu.khach_hang`
WITH CONNECTION `du_an.asia-southeast1.ket-noi-gcs`
OPTIONS (
  format = 'PARQUET',
  uris = ['gs://ho-du-lieu/khach-hang/*.parquet']
);

-- 3. Gắn policy tag vào cột nhạy cảm trong lược đồ
-- 4. Ai không có Fine-Grained Reader → không đọc được cột đó

⚠ Vì sao "tập trung" là từ khoá quan trọng:

Policy tag định nghĩa MỘT LẦN trong
    Dataplex / Data Catalog
        ↓
    Gắn vào cột ở NHIỀU BẢNG,
    kể cả BigLake table trên data lake
        ↓
    → cùng một chính sách áp cho
      cả dữ liệu trong BigQuery
      lẫn dữ liệu trong GCS
        ↓
    ⚠ Đây chính là "governed access"
      mà đội quản trị dữ liệu cần

Xem thêm câu #12965 (cùng lô): cũng dùng policy tag nhưng trên bảng thường của BigQuery. Câu này áp cùng cơ chế lên tệp trong data lake nhờ BigLake. Cùng khoá về cơ chế, nhất quán.

Vì sao các phương án khác sai

  • B (external table thường + authorized view) — đây là phương án gần nhất và che cột được bằng view, nhưng external table thường đòi người dùng có quyền trên bucket trong nhiều kịch bản, và cách này không phải kiểm soát TẬP TRUNG ở cấp cột — phải tạo và bảo trì view cho từng bảng.

  • D (bảng quản lý của BigQuery + IAM) — đòi NẠP dữ liệu vào BigQuery, trái yêu cầu truy cập tại chỗ.

  • C (Datastream với biến đổi thời gian thực) — Datastream dùng cho CDC từ CSDL quan hệ, không liên quan tới data lake Parquet.

Ghi nhớ

⚠ Ba loại bảng đọc dữ liệu ngoài — bảng phải thuộc: | Loại | Đặc điểm | |---|---| | Bảng quản lý (managed) | dữ liệu NẠP vào BigQuery — nhanh nhất, đầy đủ tính năng | | External table | đọc tại chỗ, người dùng cần quyền trên nguồn, không có bảo mật chi tiết | | BigLake table | đọc tại chỗ + BẢO MẬT CHI TIẾT + không cần quyền trên bucket | | Object table | bảng trỏ vào tệp phi cấu trúc (ảnh, video) | | Chọn BigLake khi | data lake cần quản trị |

Từ khoá nhận diện:

"data lake + quản trị + che cột" → BigLake + policy tag "truy vấn tại chỗ, không cần bảo mật chi tiết" → external table "hiệu năng tốt nhất" → nạp vào bảng quản lý "ảnh, video trong GCS" → object table "CDC từ Oracle/MySQL" → Datastream

BigLake — lợi ích cụ thể Lợi ích
Column-level security policy tag như bảng thường
Row-level security lọc dòng
Dynamic data masking che giá trị
Không cần quyền trên bucket connection đọc thay
Metadata caching tăng tốc truy vấn đáng kể
Đọc được nhiều đám mây S3, Azure Blob qua BigLake
Chia sẻ với engine khác Spark, Trino qua BigLake connector
Connection — thành phần then chốt Nội dung
Bản chất một service account do BigQuery quản lý
Quyền cần cấp roles/storage.objectViewer trên bucket cho SA đó
Người dùng cuối chỉ cần quyền trên BẢNG BigLake
Lợi ích tách quyền dữ liệu khỏi quyền hạ tầng
Tạo bằng bq mk --connection --connection_type=CLOUD_RESOURCE
Metadata caching — điều đáng bật Nội dung
Vấn đề liệt kê hàng triệu tệp mỗi lần truy vấn rất chậm
Giải pháp BigLake cache danh sách tệp và siêu dữ liệu
Cấu hình max_staleness, chế độ tự động hoặc thủ công
Kết quả truy vấn nhanh hơn nhiều lần
Đánh đổi dữ liệu mới có thể chưa thấy ngay
Kiến trúc data lake có quản trị Thành phần
Cloud Storage lưu tệp Parquet
BigLake table cửa vào có kiểm soát
Dataplex quản trị, phát hiện dữ liệu, chất lượng
Policy tag phân loại mức nhạy cảm
Sensitive Data Protection tìm PII để biết cột nào cần tag
Analytics Hub chia sẻ ra ngoài

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Bảng có phải BigLake không | bq show --format=prettyjson → có trường connectionId | | Cột nào mang policy tag | bq show --schema --format=prettyjson | | Người dùng có đọc được bucket không | không nên — kiểm tra IAM của bucket |

Và một điểm khiến BigLake khác biệt hẳn so với external table thường, đáng nhấn mạnh với đội quản trị: người dùng không cần và không nên có quyền trên bucket. Khi mọi truy cập đều đi qua BigQuery, bạn có một điểm duy nhất để áp chính sách và một dòng audit log duy nhất để kiểm tra — thay vì phải theo dõi song song cả quyền BigQuery lẫn quyền Cloud Storage.