Ngân hàng đề — Google Cloud Associate Data Practitioner
Tìm thấy 333 câu.
A data analyst needs to create a report that lists customer names and the total amount they have spent. The data exists in two BigQuery tables: customers (with columns id, name) and purchases (with columns purchase_id, customer_id, price).
Which combination of SQL clauses is required to produce the correct report?
- A JOIN and GROUP BY
- B WHERE and HAVING
- C UNION and ORDER BY
- D DISTINCT and LIMIT
Xem giải thích
Đáp án
A — JOIN và GROUP BY.
Vì sao đúng
Báo cáo cần tên khách hàng (nằm ở bảng customers) và tổng số tiền đã chi (tính từ bảng purchases). Lấy dữ liệu từ hai bảng cần JOIN; tính tổng cho từng khách cần GROUP BY.
⚠ Điểm mấu chốt — hai mệnh đề giải hai nửa của bài toán:
"tên khách hàng" → ở bảng customers
"tổng số tiền đã chi" → tính từ bảng purchases
↓
Cần dữ liệu từ HAI bảng
↓
→ JOIN
"TỔNG cho TỪNG khách hàng"
↓
→ GROUP BY
⚠ Truy vấn hoàn chỉnh:
SELECT
c.name,
SUM(p.price) AS tong_chi_tieu
FROM `du_an.customers` AS c
JOIN `du_an.purchases` AS p
ON p.customer_id = c.id
GROUP BY c.name;
↓
⚠ Mọi cột trong SELECT phải nằm trong
GROUP BY hoặc trong hàm tổng hợp
⚠ Một chi tiết dễ sai — gom theo name hay theo id:
GROUP BY c.name
↓
⚠ Hai khách hàng TRÙNG TÊN
sẽ bị GỘP làm một
↓
An toàn hơn:
SELECT c.id, c.name, SUM(p.price)
...
GROUP BY c.id, c.name
↓
→ gom theo KHOÁ, hiển thị tên
⚠ Và khách hàng CHƯA mua gì thì sao:
JOIN (INNER)
→ chỉ khách CÓ giao dịch mới xuất hiện
LEFT JOIN
→ giữ MỌI khách hàng
→ khách chưa mua có SUM = NULL
↓
Dùng IFNULL(SUM(p.price), 0)
để hiện 0 thay vì NULL
↓
⚠ Chọn kiểu JOIN theo Ý ĐỊNH NGHIỆP VỤ
của báo cáo
Xem thêm câu #12942 (lô 134): hỏi riêng về mệnh đề nối bảng →
JOIN ... ON. Và #12938 (lô 134): hỏi riêng về tính tổng theo nhóm →GROUP BY. Câu này cần cả hai — ba câu nhất quán.
Vì sao các phương án khác sai
-
B (
WHEREvàHAVING) — đây là phương án gần nhất vìWHEREcó thể nối bảng theo cú pháp cũ, nhưng cả hai đều là mệnh đề LỌC; không cái nào tạo ra phép tính tổng theo nhóm. -
C (
UNIONvàORDER BY) —UNIONchồng dòng theo chiều DỌC, không lấy được cột từ bảng kia. -
D (
DISTINCTvàLIMIT) — loại trùng và cắt số dòng; không tính tổng, không nối bảng.
Ghi nhớ
⚠ Mệnh đề nào cho việc gì — bảng phải thuộc: | Nhu cầu | Mệnh đề | |---|---| | Lấy cột từ NHIỀU bảng | JOIN ... ON | | Tính tổng/đếm/trung bình theo nhóm | GROUP BY + hàm tổng hợp | | Lọc dòng | WHERE | | Lọc nhóm sau khi gom | HAVING | | Chồng dòng của hai tập kết quả | UNION ALL | | Loại dòng trùng | DISTINCT | | Xếp hạng trong nhóm | hàm cửa sổ |
Từ khoá nhận diện:
"tên từ bảng A, tổng từ bảng B" →
JOIN+GROUP BY"chỉ lấy khách chi trên 10 triệu" → thêmHAVING"cả khách chưa mua gì" →LEFT JOIN"top 5 mỗi nhóm" → hàm cửa sổ "gộp dữ liệu hai năm" →UNION ALL
| Ba cái bẫy của JOIN + GROUP BY | Bẫy |
|---|---|
| Nhân bản dòng | khoá bên phải không duy nhất → tổng bị THỔI PHỒNG |
| Mất khách hàng | dùng INNER JOIN khi cần LEFT JOIN |
| Gom theo tên thay vì khoá | trùng tên bị gộp |
| Cách phát hiện | so tổng doanh thu với tổng của riêng bảng purchases |
| Kiểm khoá | SELECT id, COUNT(*) FROM customers GROUP BY 1 HAVING COUNT(*)>1 |
| Truy vấn đầy đủ hơn cho báo cáo thật | Thành phần |
|---|---|
LEFT JOIN |
giữ cả khách chưa mua |
IFNULL(SUM(price), 0) |
hiện 0 thay vì NULL |
GROUP BY c.id, c.name |
gom theo khoá |
ORDER BY tong_chi_tieu DESC |
xếp hạng |
WHERE p.ngay >= ... |
giới hạn kỳ báo cáo |
HAVING SUM(p.price) > 0 |
lọc nhóm nếu cần |
| Hiệu năng trong BigQuery | Cách |
|---|---|
| Bảng lớn JOIN bảng NHỎ | BigQuery dùng broadcast join — rất nhanh |
| Lọc TRƯỚC khi join | giảm dữ liệu phải trộn |
| Chọn ít cột | lưu trữ theo cột |
| Cân nhắc bảng LỒNG | ARRAY<STRUCT> — tránh join hẳn |
| Kiểm tra | Execution details — xem bytes shuffled |
| Kiểm tra kết quả báo cáo | Việc |
|---|---|
| Tổng chung có khớp không | so với SELECT SUM(price) FROM purchases |
| Số khách có đúng không | so với COUNT(DISTINCT id) |
| Có khách nào thiếu không | thử LEFT JOIN và tìm NULL |
| Có giá trị âm hay bất thường | MIN, MAX |
| Nguyên tắc | luôn có một phép kiểm chứng độc lập |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | JOIN có nhân bản dòng không | so COUNT(*) trước và sau | | Tổng có khớp không | so với tổng của riêng bảng purchases | | Có khách bị bỏ sót không | LEFT JOIN + WHERE p.customer_id IS NULL |
Và một phép kiểm chứng nên gắn kèm mọi báo cáo dạng này: so tổng doanh thu trong báo cáo với tổng của riêng bảng giao dịch. Nếu con số trong báo cáo lớn hơn, phép JOIN đang nhân bản dòng ở đâu đó — và đó là loại lỗi cho ra một bảng số liệu trông hoàn toàn hợp lý, chỉ có điều mọi con số đều sai.
You need to migrate a 5 TB on-premises PostgreSQL database to Cloud SQL for PostgreSQL. The business requires that the application using the database experiences minimal downtime during the migration process. You need a managed Google Cloud service that can replicate the data from the live on-premises database to the Cloud SQL instance.
Which service should you use?
- A Database Migration Service (DMS)
- B Cloud Data Fusion
- C BigQuery Data Transfer Service
- D Transfer Appliance
Xem giải thích
Đáp án
A — Database Migration Service (DMS).
Vì sao đúng
Đề nêu bốn điều: PostgreSQL tại chỗ → Cloud SQL for PostgreSQL, 5 TB, thời gian ngừng tối thiểu, và cần dịch vụ được quản lý có nhân bản từ CSDL đang chạy. DMS được thiết kế cho chính xác việc này.
⚠ Điểm mấu chốt — DMS làm di chuyển TRỰC TUYẾN:
1. FULL DUMP
→ sao chép 5 TB dữ liệu hiện có
→ CSDL nguồn VẪN PHỤC VỤ bình thường
2. CDC (change data capture)
→ đọc WAL của PostgreSQL
→ phát lại mọi thay đổi lên Cloud SQL
→ bám theo liên tục
3. CUTOVER
→ khi replication lag ≈ 0
→ dừng ghi vài phút, thăng cấp đích
↓
⚠ Thời gian ngừng: VÀI PHÚT
thay vì nhiều giờ
⚠ Điều kiện phía nguồn PostgreSQL:
wal_level = logical
max_replication_slots ≥ số cần dùng
max_wal_senders ≥ số cần dùng
↓
+ extension pglogical (với một số phiên bản)
+ tài khoản có quyền REPLICATION
+ MỌI BẢNG PHẢI CÓ KHOÁ CHÍNH
↓
⚠ Bảng thiếu khoá chính là vấn đề
hay chặn kế hoạch nhất
⚠ Vì sao DMS đáng chọn hơn tự dựng nhân bản:
- MIỄN PHÍ với chuyển đồng nhất
(PostgreSQL → Cloud SQL for PostgreSQL)
- Kiểm tra tương thích TRƯỚC khi chạy
- Tự tạo instance đích
- Theo dõi replication lag trong console
- Thăng cấp bằng một thao tác
- Không phải tự vận hành slot và WAL
Xem thêm câu #12987 (cùng lô): cũng khoá DMS, ở đó là so sánh với Data Fusion. Và #12986 (cùng lô) về khái niệm online migration. Ba câu nhất quán — cùng một chủ đề nhìn từ ba góc.
Vì sao các phương án khác sai
-
B (Cloud Data Fusion) — đây là phương án gần nhất trong nhóm công cụ dữ liệu, nhưng nó là ETL cho phân tích: không tạo ra một CSDL vận hành thay thế, và không có CDC liên tục cho việc di chuyển.
-
C (BigQuery Data Transfer Service) — nạp dữ liệu vào BigQuery, không phải vào Cloud SQL.
-
D (Transfer Appliance) — thiết bị vật lý cho TỆP dung lượng rất lớn; 5 TB truyền qua mạng hoàn toàn khả thi, và thiết bị vật lý không có CDC nên không giảm được thời gian ngừng.
Ghi nhớ
⚠ Chọn dịch vụ theo NGUỒN và ĐÍCH — bảng phải thuộc: | Nguồn → Đích | Dịch vụ | |---|---| | CSDL → Cloud SQL / AlloyDB | Database Migration Service | | CSDL → BigQuery (CDC) | Datastream | | Nhiều nguồn → BigQuery, có biến đổi | Cloud Data Fusion, Dataflow | | SaaS → BigQuery | BigQuery Data Transfer Service | | Kho đối tượng → GCS | Storage Transfer Service | | Hàng trăm TB, băng thông kém | Transfer Appliance |
Từ khoá nhận diện:
"PostgreSQL tại chỗ → Cloud SQL, ít thời gian ngừng" → DMS "CSDL → BigQuery gần thời gian thực" → Datastream "cần biến đổi dữ liệu" → Data Fusion / Dataflow "5 TB qua mạng" → hoàn toàn khả thi, không cần thiết bị vật lý "hàng trăm TB, mạng chậm" → Transfer Appliance
| Bốn giai đoạn của một job DMS | Giai đoạn |
|---|---|
| Kiểm tra | DMS tự chạy test kết nối và tương thích |
| Full dump | sao chép dữ liệu hiện có |
| CDC | bám theo thay đổi — theo dõi lag |
| Promote | thăng cấp đích thành CSDL độc lập |
| Sau đó | cấu hình HA, replica, sao lưu cho instance mới |
| Kết nối tới CSDL tại chỗ | Cách |
|---|---|
| Cloud VPN | phổ biến, dễ dựng |
| Dedicated / Partner Interconnect | băng thông lớn |
| Reverse SSH tunnel | DMS hỗ trợ cho trường hợp đơn giản |
| IP allowlist | ít an toàn hơn |
| Băng thông | 5 TB cần tính thời gian dump ban đầu |
| Kế hoạch cắt chuyển cho 5 TB | Bước |
|---|---|
| 1 | Chạy full dump trước nhiều ngày |
| 2 | Theo dõi lag trong giai đoạn CDC |
| 3 | Kiểm thử ứng dụng trên bản sao |
| 4 | Đối chiếu số dòng và checksum |
| 5 | Đặt cửa sổ cắt chuyển ngắn, dừng ghi, đợi lag = 0 |
| 6 | Thăng cấp, đổi chuỗi kết nối |
| 7 | GIỮ nguồn vài ngày để quay lui |
| Sau khi thăng cấp — đừng quên | Việc |
|---|---|
| Bật HA | instance mới chưa có |
| Bật sao lưu tự động và PITR | |
| Tạo read replica nếu cần | |
| Bật deletion protection | |
ANALYZE / cập nhật thống kê |
hiệu năng truy vấn |
| Đo lại hiệu năng | so với hệ thống cũ |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | Job đang ở giai đoạn nào | console → Database Migration → Migration jobs | | Độ trễ nhân bản | cùng màn hình, chỉ số replication delay | | Dữ liệu đã khớp chưa | so COUNT(*) từng bảng trước khi cắt chuyển |
Và một điều kiện kỹ thuật nên kiểm tra ngay ở giai đoạn khảo sát, trước khi hứa hẹn thời gian ngừng với bên nghiệp vụ: mọi bảng đã có khoá chính chưa. Nhân bản logic của PostgreSQL cần khoá để xác định dòng nào thay đổi, và một bảng lịch sử cũ không có khoá chính có thể buộc cả kế hoạch phải đổi cách tiếp cận — tốt hơn là biết điều đó từ tuần đầu tiên.
A weekly machine learning workflow must be automated. The workflow has three sequential steps that all run in BigQuery:
1. Run a SQL script to preprocess data and create a training table.
2. Use the training table to train a BQML model.
3. After the model is trained, run an evaluation function. Each step must only start after the previous one has successfully completed.
Which service is designed to orchestrate this dependent sequence of tasks?
- A A single Cloud Function that runs all three jobs.
- B Three separate BigQuery scheduled queries set to run 10 minutes apart.
- C Cloud Composer
- D The BigQuery UI.
Xem giải thích
Đáp án
C — Cloud Composer.
Vì sao đúng
Đề mô tả ba bước TUẦN TỰ, mỗi bước chỉ được chạy khi bước trước THÀNH CÔNG. Đó chính là định nghĩa của điều phối có phụ thuộc.
⚠ Điểm mấu chốt — DAG diễn đạt chính xác luồng trong đề:
with DAG('ml_hang_tuan', schedule='0 2 * * 1') as dag:
tien_xu_ly = BigQueryInsertJobOperator(
task_id='tien_xu_ly',
configuration={'query': {
'query': 'CREATE OR REPLACE TABLE ...',
'useLegacySql': False}})
huan_luyen = BigQueryInsertJobOperator(
task_id='huan_luyen',
configuration={'query': {
'query': 'CREATE OR REPLACE MODEL ...',
'useLegacySql': False}})
danh_gia = BigQueryInsertJobOperator(
task_id='danh_gia',
configuration={'query': {
'query': 'SELECT * FROM ML.EVALUATE(...)',
'useLegacySql': False}})
tien_xu_ly >> huan_luyen >> danh_gia
⚠ ⚠ Vì sao "ba scheduled query cách nhau 10 phút" là bẫy chính:
Bước 1 mất 10 phút hôm nay
↓
Tuần sau dữ liệu tăng gấp đôi
↓
Bước 1 mất 25 phút
↓
⚠ Bước 2 vẫn khởi động sau 10 phút
→ huấn luyện trên bảng CHƯA XONG
hoặc bảng của TUẦN TRƯỚC
↓
⚠ Bước 1 THẤT BẠI
→ bước 2 và 3 VẪN CHẠY
→ mô hình huấn luyện trên dữ liệu cũ
→ KHÔNG có lỗi nào báo ra
↓
→ "đợi 10 phút" là HY VỌNG,
không phải PHỤ THUỘC
⚠ Điều Composer cho mà cách kia không có:
- Bước sau chỉ chạy khi bước trước THÀNH CÔNG
- Thử lại theo TỪNG bước
- Chạy lại từ đúng bước hỏng
- Một màn hình xem trạng thái cả luồng
- Cảnh báo khi luồng chậm (SLA)
- Backfill cho tuần đã lỡ
Xem thêm câu #12996 (cùng lô) và #12948 (lô 134): cùng khoá Cloud Composer, cùng lý do phụ thuộc nhiều bước. Và #13000 (cùng lô) khoá Cloud Scheduler vì chỉ có một job duy nhất. Bốn câu, một hệ quy tắc nhất quán.
Vì sao các phương án khác sai
-
B (ba scheduled query cách nhau 10 phút) — đây là phương án bẫy chính: thời gian chờ KHÔNG PHẢI phụ thuộc. Bước trước chậm hoặc hỏng thì bước sau vẫn chạy trên dữ liệu sai.
-
A (một Cloud Function chạy cả ba) — hàm phải tự chờ từng job BigQuery, dễ chạm giới hạn thời gian, và bạn phải tự viết lại toàn bộ logic thử lại và theo dõi.
-
D (giao diện BigQuery) — thủ công, không phải tự động hoá.
Ghi nhớ
⚠ Phụ thuộc thật ↔ thời gian chờ — bảng phải thuộc: | Cách | Bản chất | |---|---| | task_a >> task_b trong DAG | PHỤ THUỘC THẬT — chờ thành công | | Hai job cách nhau N phút | HY VỌNG — không kiểm tra gì | | Sensor chờ điều kiện | phụ thuộc theo trạng thái dữ liệu | | Trigger theo sự kiện | phụ thuộc theo sự kiện | | Nguyên tắc | đừng bao giờ dùng thời gian thay cho phụ thuộc |
Từ khoá nhận diện:
"chỉ chạy khi bước trước thành công" → Cloud Composer "cách nhau N phút" → bẫy kinh điển, luôn sai "một job theo lịch" → Cloud Scheduler "chỉ toàn SQL trong BigQuery, cần kiểm thử" → Dataform cũng là lựa chọn tốt "vài bước nhẹ, muốn rẻ" → Cloud Workflows
| Với luồng TOÀN BỘ trong BigQuery — hai lựa chọn tốt | Lựa chọn |
|---|---|
| Cloud Composer | đáp án của đề — mạnh nhất, có DAG đầy đủ |
| Dataform | quản lý phụ thuộc giữa các bước SQL, có kiểm thử, miễn phí |
| Chọn Composer khi | luồng còn chạm tới dịch vụ khác |
| Chọn Dataform khi | hoàn toàn trong BigQuery và muốn tiết kiệm |
| Cloud Workflows | cũng làm được, khai bằng YAML, rẻ |
| Cấu hình DAG nên có | Cấu hình |
|---|---|
retries và retry_delay |
chịu lỗi tạm thời |
trigger_rule |
mặc định all_success — đúng cho đề này |
execution_timeout |
tránh treo mãi |
| SLA | cảnh báo khi luồng CHẬM, không chỉ khi hỏng |
BigQueryCheckOperator |
kiểm tra dữ liệu giữa các bước |
catchup=False |
tránh chạy dồn khi mới bật DAG |
| Luồng ML hằng tuần nên thêm gì | Bước |
|---|---|
| Kiểm tra chất lượng dữ liệu trước khi huấn luyện | |
| So chỉ số mô hình MỚI với mô hình CŨ | |
| Chỉ triển khai nếu tốt hơn | rẽ nhánh trong DAG |
| Lưu lịch sử chỉ số | phát hiện trôi theo thời gian |
| Cảnh báo khi chất lượng giảm |
| Vì sao "im lặng sai" nguy hiểm hơn "báo lỗi" | Nội dung |
|---|---|
| Job thất bại | có người biết, có người sửa |
| Job chạy trên dữ liệu cũ | không ai biết trong nhiều tuần |
| Với mô hình ML | dự đoán sai lệch dần mà không có tín hiệu |
| Vì vậy | phụ thuộc tường minh + kiểm tra dữ liệu |
| Nguyên tắc | thà dừng còn hơn chạy sai |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | Bước nào hỏng | Airflow Graph view | | Bước trước có thật sự xong chưa | kiểm tra thời gian kết thúc của task | | Mô hình có được huấn luyện trên dữ liệu mới không | ML.TRAINING_INFO và thời điểm tạo bảng |
Và một lý do rất thực tế để không bao giờ dùng "cách nhau 10 phút" cho luồng huấn luyện mô hình: nó hỏng theo kiểu im lặng. Job vẫn xanh, mô hình vẫn được tạo, chỉ có điều nó học trên dữ liệu của tuần trước — và loại sai lệch đó tích tụ dần cho tới khi ai đó tình cờ so hai con số và phát hiện ra mọi thứ đã lệch từ lâu.
What is the fundamental difference in how AEAD (Authenticated Encryption with Associated Data) functions and Dynamic Data Masking protect data in a BigQuery column?
- A AEAD is a table-level control, while masking is a column-level control.
- B AEAD is an older, legacy feature, while masking is a modern feature.
- C AEAD encrypts the data so it is stored as ciphertext at rest, while masking obscures plaintext data at query time.
- D AEAD is managed with IAM (Identity and Access Management) policies, while masking is managed with SQL (Structured Query Language) views.
Xem giải thích
Đáp án
C — AEAD MÃ HOÁ dữ liệu nên nó được lưu ở dạng BẢN MÃ trên đĩa, còn masking CHE dữ liệu nguyên văn NGAY LÚC TRUY VẤN.
Vì sao đúng
Khác biệt cơ bản nằm ở dữ liệu được lưu ở dạng nào và thời điểm phép bảo vệ xảy ra.
⚠ Điểm mấu chốt — hai trục phân biệt:
AEAD
↓
Dữ liệu ghi vào bảng đã là BẢN MÃ
↓
→ nhìn thẳng vào bảng chỉ thấy chuỗi byte
→ muốn đọc phải GỌI HÀM GIẢI MÃ
kèm KHOÁ
↓
Bảo vệ xảy ra LÚC GHI
DYNAMIC DATA MASKING
↓
Dữ liệu trên đĩa là NGUYÊN VĂN
↓
→ BigQuery che giá trị KHI TRẢ KẾT QUẢ,
tuỳ vai trò người truy vấn
↓
Bảo vệ xảy ra LÚC ĐỌC
⚠ AEAD trông thế nào trong SQL:
-- ghi
INSERT INTO t (email_ma)
SELECT AEAD.ENCRYPT(
(SELECT keyset FROM khoa),
email,
'ngu_canh_bo_sung');
-- đọc
SELECT AEAD.DECRYPT_STRING(
(SELECT keyset FROM khoa),
email_ma,
'ngu_canh_bo_sung');
↓
⚠ "Associated data" (ngữ cảnh bổ sung)
được XÁC THỰC nhưng KHÔNG mã hoá
→ chống việc hoán đổi bản mã
giữa các dòng
⚠ Hệ quả thực tế của việc lưu bản mã:
Cột đã mã hoá bằng AEAD
↓
⚠ KHÔNG lọc được: WHERE email = '...'
⚠ KHÔNG nối bảng theo cột đó
⚠ KHÔNG gom nhóm được
⚠ Nén kém hơn
↓
→ chỉ dùng khi THẬT SỰ cần
dữ liệu ở dạng bản mã trong bảng
Xem thêm câu #12982 (cùng lô): hỏi chọn cơ chế nào cho tình huống che số điện thoại → dynamic data masking. Câu này hỏi khác biệt cơ bản giữa hai cơ chế. Và #12931 (lô 133) về CMEK — quản lý khoá, một tầng khác nữa. Ba câu nhất quán.
Vì sao các phương án khác sai
-
A (AEAD ở cấp bảng, masking ở cấp cột) — sai: cả hai đều áp ở cấp CỘT. AEAD là hàm SQL dùng trên một cột; masking gắn vào cột qua policy tag.
-
B (AEAD là tính năng cũ, masking là hiện đại) — sai; cả hai đều là tính năng hiện hành, phục vụ hai mục đích khác nhau.
-
D (AEAD quản lý bằng IAM, masking bằng view SQL) — sai cả hai vế: AEAD quản lý bằng khoá trong SQL, còn masking quản lý bằng policy tag và IAM.
Ghi nhớ
⚠ Ba cơ chế bảo vệ cột — bảng phải thuộc: | Cơ chế | Dữ liệu trên đĩa | Bảo vệ xảy ra khi | Vẫn lọc/join được? | |---|---|---|---| | Column-level security | nguyên văn | lúc đọc | có (nếu đủ quyền) | | Dynamic data masking | nguyên văn | lúc đọc | có (giá trị bị che) | | AEAD | BẢN MÃ | lúc ghi | KHÔNG |
Từ khoá nhận diện:
"dữ liệu phải là bản mã trong bảng" → AEAD "dữ liệu gốc nguyên vẹn, che khi truy vấn" → masking "chặn hẳn không cho đọc cột" → column-level security "ai giữ khoá mã hoá đĩa" → CMEK / GMEK — tầng khác hẳn "lọc dòng theo người dùng" → row-level security
| Khi nào thật sự cần AEAD | Trường hợp |
|---|---|
| Quy định bắt dữ liệu là bản mã ngay trong bảng | |
| Mỗi khách hàng một khoá riêng | cách ly tuyệt đối |
| Crypto-shredding | xoá khoá = xoá dữ liệu của khách đó |
| Không tin cả quản trị viên BigQuery | họ thấy bảng nhưng không giải mã được |
| Còn lại | masking hoặc CLS đơn giản hơn nhiều |
| Quản lý khoá cho AEAD | Cách |
|---|---|
KEYS.NEW_KEYSET('AEAD_AES_GCM_256') |
tạo keyset |
| Lưu keyset ở đâu | bảng riêng có quyền rất hẹp, hoặc Cloud KMS |
KEYS.KEYSET_CHAIN |
bọc keyset bằng khoá KMS — cách an toàn nhất |
| Xoay khoá | thêm khoá mới vào keyset, mã hoá lại dần |
| Mất keyset | mất dữ liệu vĩnh viễn |
| Ba tầng mã hoá của BigQuery — đừng lẫn | Tầng |
|---|---|
| Mã hoá đĩa mặc định | GMEK — luôn bật, không tắt được |
| CMEK | bạn quản khoá đĩa qua Cloud KMS |
| AEAD | mã hoá Ở CẤP CỘT bằng SQL |
| Ba tầng | độc lập, dùng chồng lên nhau được |
| Câu hỏi thường lẫn | "mã hoá" ở đây là tầng nào |
| Chọn cơ chế theo yêu cầu | Yêu cầu |
|---|---|
| "Người thường thấy bản che, người có quyền thấy đủ" | masking |
| "Người thường không được đọc cột đó" | column-level security |
| "Dữ liệu trong bảng phải là bản mã" | AEAD |
| "Chúng tôi phải giữ khoá đĩa" | CMEK |
| "Chỉ thấy dòng của mình" | row-level security |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | Cột đang lưu bản mã hay nguyên văn | truy vấn thử bằng tài khoản đặc quyền | | Quy tắc che là gì | Dataplex → Data policies | | Keyset AEAD ai truy cập được | quyền của bảng chứa keyset, hoặc IAM của khoá KMS |
Và một cái giá của AEAD cần cân nhắc rất kỹ trước khi chọn: cột đã mã hoá gần như không dùng được cho phân tích. Không lọc, không nối bảng, không gom nhóm theo cột đó — nên nếu mục tiêu chỉ là "người thường không nhìn thấy số điện thoại đầy đủ", masking cho cùng kết quả bảo mật mà giữ nguyên khả năng phân tích của kho dữ liệu.
An analyst frequently joins a 5 TB fact_sales table with a 500 MB dim_store table in BigQuery using the store_id column. These queries are running slower than desired. The fact_sales table is already partitioned by transaction_date.
What additional optimization should you apply to the fact_sales table to improve the performance of this specific join?
- A Recreate the fact_sales table and add clustering on the store_id column.
- B Enable BigQuery's long-term storage pricing.
- C Increase the number of slots in your reservation.
- D Export the dim_store table to a Google Sheet.
Xem giải thích
Đáp án
A — Tạo lại bảng fact_sales và thêm PHÂN CỤM (clustering) theo cột store_id.
Vì sao đúng
Bảng đã phân vùng theo transaction_date, nên phần tối ưu theo thời gian đã có. Nút thắt còn lại là phép JOIN theo store_id, và phân cụm theo chính cột đó là công cụ dành cho việc này.
⚠ Điểm mấu chốt — phân vùng và phân cụm giải hai bài toán khác nhau:
PARTITION BY transaction_date (đã có)
↓
→ cắt bỏ hẳn những NGÀY không cần
CLUSTER BY store_id (thêm vào)
↓
→ SẮP XẾP dữ liệu theo store_id
BÊN TRONG mỗi phân vùng
↓
→ các dòng cùng store_id nằm CẠNH NHAU
→ BigQuery bỏ qua các KHỐI không chứa
store_id đang cần
→ JOIN và lọc theo store_id nhanh hơn hẳn
⚠ Tạo lại bảng:
CREATE TABLE `du_an.fact_sales_moi`
PARTITION BY DATE(transaction_date)
CLUSTER BY store_id
AS SELECT * FROM `du_an.fact_sales`;
↓
⚠ Không đổi bảng đang có tại chỗ được
→ tạo bảng mới rồi chuyển sang
⚠ Vì sao JOIN 5 TB với 500 MB lại chậm dù đã có broadcast:
BigQuery thường BROADCAST bảng nhỏ
(500 MB) tới mọi worker
↓
→ phần join đã khá tốt
↓
Nhưng vẫn phải ĐỌC và XỬ LÝ
toàn bộ phần fact_sales liên quan
↓
Phân cụm theo store_id giúp:
- lọc theo store_id rẻ hơn nhiều
- dữ liệu cùng store gom lại
→ ít khối phải đọc
⚠ Bốn cột phân cụm — thứ tự có ý nghĩa:
CLUSTER BY a, b, c, d
↓
Sắp xếp theo a, rồi trong a sắp theo b...
↓
⚠ Lọc theo `a` → rất hiệu quả
⚠ Lọc CHỈ theo `c` → gần như không lợi
↓
→ đặt cột LỌC NHIỀU NHẤT lên trước
Xem thêm câu #12979 (lô 134): cùng chủ đề tối ưu bảng lớn, nhưng ở đó bảng CHƯA phân vùng và truy vấn lọc theo NGÀY → khoá là phân vùng. Câu này bảng đã phân vùng theo ngày rồi, nút thắt là JOIN theo
store_id→ phân cụm. Hai khoá khác nhau vì tình huống khác nhau — hoàn toàn nhất quán.
Vì sao các phương án khác sai
-
C (mua thêm slot) — đây là phương án hay bị chọn khi truy vấn chậm, nhưng nó chỉ cấp thêm năng lực tính toán cho cùng một khối lượng dữ liệu phải quét; tốn tiền mà không sửa gốc rễ.
-
B (bật giá long-term storage) — long-term storage là TỰ ĐỘNG và chỉ ảnh hưởng giá lưu trữ, không liên quan tới hiệu năng truy vấn.
-
D (xuất
dim_storesang Google Sheet) — làm chậm hơn nhiều: bảng ngoài trỏ vào Sheet chậm hơn hẳn bảng thường.
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 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í | đoán trước được | không đoán trước được | | Hợp với | lọc theo NGÀY | lọc/join theo cột có nhiều giá trị | | Nên dùng | CẢ HAI cùng lúc |
Từ khoá nhận diện:
"đã phân vùng rồi, join chậm" → thêm phân cụm theo cột join "luôn lọc theo ngày" → phân vùng "lọc theo nhiều cột khác nhau" → phân cụm "mua thêm slot" → giải pháp cuối cùng, không phải đầu tiên "truy vấn lặp lại tốn kém" → materialized view
| Chọn cột phân cụm thế nào | Nguyên tắc |
|---|---|
Cột hay dùng trong WHERE và JOIN |
như store_id ở đây |
| Nhiều giá trị phân biệt (high cardinality) | phân cụm mới có tác dụng |
| Đặt cột LỌC NHIỀU NHẤT lên TRƯỚC | thứ tự quan trọng |
| Tối đa 4 cột | thêm nữa không được |
| Cột ít giá trị (như giới tính) | phân cụm gần như vô ích |
| Vì sao phân cụm không "đoán trước" được chi phí | Nội dung |
|---|---|
| Ước tính trước truy vấn | KHÔNG phản ánh phần cắt được nhờ phân cụm |
| Phần cắt thật | chỉ biết SAU KHI chạy |
| Vì vậy | --dry_run cho số byte cao hơn thực tế |
| Kiểm tra thật | so total_bytes_billed trong INFORMATION_SCHEMA.JOBS |
| Phân vùng thì ngược lại | cắt được biết trước |
| Các cách tối ưu JOIN trong BigQuery | Cách |
|---|---|
| Phân cụm theo khoá join | như đề này |
| Lọc TRƯỚC khi join | giảm dữ liệu phải trộn |
| Bảng nhỏ để BigQuery broadcast | tự động khi đủ nhỏ |
Phi chuẩn hoá bằng ARRAY<STRUCT> |
tránh join hẳn |
| Materialized view | cho truy vấn lặp lại |
| Kiểm tra | Execution details → bytes shuffled |
| Bảo trì phân cụm | Nội dung |
|---|---|
| BigQuery TỰ tái phân cụm | miễn phí, chạy nền |
| Ghi mới liên tục | dữ liệu mới chưa sắp ngay |
| Không cần làm gì thủ công | khác với chỉ mục của CSDL truyền thống |
| Đổi cột phân cụm | ALTER TABLE ... SET OPTIONS, chỉ áp cho dữ liệu mới |
| Muốn áp cho toàn bộ | tạo lại bảng |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | Bảng có phân cụm chưa | bq show <dataset>.<bảng> → Clustered By | | Truy vấn có nhanh hơn không | so total_bytes_billed và slot time trước/sau | | Bước nào tốn nhất | Execution details của job |
Và một thứ tự xử lý đáng nhớ khi một truy vấn BigQuery chạy chậm: giảm dữ liệu phải quét trước, mua thêm năng lực tính toán sau cùng. Phân vùng, phân cụm, chọn ít cột và materialized view đều tấn công vào lượng dữ liệu; thêm slot chỉ giúp xử lý cùng lượng dữ liệu ấy nhanh hơn — và gần như luôn đắt hơn.
A company has over 100 analysts organized into four different departments. All analysts frequently query the same set of large, multi-terabyte tables in BigQuery to build reports. Many of their queries perform similar complex aggregations and joins to calculate key business metrics, such as daily active users or monthly revenue.
This pattern of repeated, heavy queries is leading to high and unpredictable costs. The company needs a solution that can pre-calculate the results of these common, expensive queries. The solution should be largely transparent to the analysts, allowing them to continue querying the base tables while benefiting from reduced costs and faster performance, with the pre-calculated data being refreshed automatically.
Which BigQuery feature is the most effective solution to meet these requirements?
-
A
Materialized Views
-
B
Scheduled Queries writing to summary tables
-
C
Analytics Hub
-
D
BigQuery Caching
Xem giải thích
Đáp án
A — Materialized Views (khung nhìn được vật chất hoá).
Vì sao đúng
Đề nêu ba yêu cầu: tính trước kết quả của các truy vấn nặng hay lặp lại, trong suốt với người dùng (họ vẫn viết truy vấn như cũ), và giảm chi phí khó lường. Materialized view làm đúng cả ba.
⚠ Điểm mấu chốt — BigQuery TỰ dùng materialized view:
Tạo materialized view tính sẵn
doanh thu theo ngày
↓
Nhà phân tích viết truy vấn
trên BẢNG GỐC như bình thường
↓
⚠ BigQuery TỰ NHẬN RA có thể trả lời
từ materialized view
→ tự viết lại truy vấn (smart tuning)
↓
→ nhà phân tích KHÔNG PHẢI ĐỔI GÌ
→ chi phí và thời gian giảm mạnh
↓
Đây chính là "trong suốt với người dùng"
⚠ Tạo materialized view:
CREATE MATERIALIZED VIEW `du_an.mv_doanh_thu_ngay`
PARTITION BY ngay
CLUSTER BY phong_ban
OPTIONS (
enable_refresh = true,
refresh_interval_minutes = 30
) AS
SELECT
DATE(thoi_diem) AS ngay,
phong_ban,
COUNT(DISTINCT user_id) AS nguoi_dung,
SUM(doanh_thu) AS tong_doanh_thu
FROM `du_an.su_kien`
GROUP BY ngay, phong_ban;
⚠ Làm mới GIA TĂNG — điểm mạnh nhất:
Bảng gốc có dữ liệu mới
↓
⚠ Materialized view KHÔNG tính lại
từ đầu
→ chỉ xử lý PHẦN THAY ĐỔI
↓
→ luôn cập nhật, chi phí thấp
↓
Và ngay cả khi chưa kịp làm mới,
BigQuery vẫn cho kết quả ĐÚNG bằng
cách kết hợp view với phần dữ liệu mới
Xem thêm câu #13005 (cùng lô): cũng về tối ưu truy vấn nặng, nhưng bằng phân cụm. Hai kỹ thuật bổ sung nhau: phân vùng và phân cụm giảm dữ liệu phải quét; materialized view tránh TÍNH LẠI.
Vì sao các phương án khác sai
-
B (scheduled query ghi vào bảng tổng hợp) — đây là phương án gần nhất và rất phổ biến trong thực tế, nhưng nó KHÔNG trong suốt: nhà phân tích phải biết và tự trỏ vào bảng tổng hợp. Nó cũng không tự làm mới gia tăng và dữ liệu cũ tới lần chạy kế tiếp.
-
D (BigQuery caching) — cache chỉ áp cho truy vấn GIỐNG HỆT NHAU của cùng người dùng, hết hạn sau 24 giờ và mất hiệu lực khi bảng thay đổi. Với 100 nhà phân tích viết các truy vấn hơi khác nhau, cache gần như không giúp gì.
-
C (Analytics Hub) — công cụ chia sẻ dataset, không tính trước gì cả.
Ghi nhớ
⚠ Bốn cách giảm chi phí truy vấn lặp lại — bảng phải thuộc: | Cách | Trong suốt? | Tự làm mới? | |---|---|---| | Materialized view | CÓ — BigQuery tự dùng | CÓ, gia tăng | | Bảng tổng hợp + scheduled query | không — phải tự trỏ vào | theo lịch, tính lại | | BigQuery cache | có | chỉ với truy vấn giống hệt | | BI Engine | CÓ — tăng tốc trong suốt | tự động | | Phân vùng + phân cụm | có | không áp dụng |
Từ khoá nhận diện:
"tính trước, trong suốt với người dùng" → materialized view "tăng tốc dashboard" → BI Engine "bảng tổng hợp theo lịch" → scheduled query — không trong suốt "cùng một truy vấn chạy lại" → cache — miễn phí nhưng hạn chế "chia sẻ dataset" → Analytics Hub
| Materialized view — giới hạn cần biết | Giới hạn |
|---|---|
| Chỉ hỗ trợ một tập SQL nhất định | GROUP BY, phần lớn hàm tổng hợp |
COUNT(DISTINCT) |
dùng APPROX_COUNT_DISTINCT hoặc HLL |
| Hạn chế với JOIN | có hỗ trợ nhưng kèm điều kiện |
Không có ORDER BY, LIMIT |
trong định nghĩa |
| Không dùng hàm không tất định | CURRENT_TIMESTAMP()... |
| Tối đa 20 view trên một bảng gốc |
| Chi phí của materialized view | Khoản |
|---|---|
| Lưu trữ | như một bảng — thường nhỏ hơn nhiều bảng gốc |
| Làm mới | tính theo byte xử lý của phần thay đổi |
| Truy vấn | rẻ hơn hẳn so với quét bảng gốc |
| Tắt tự làm mới | enable_refresh = false rồi làm mới thủ công |
| Cân nhắc | bảng gốc thay đổi liên tục → chi phí làm mới cao |
| BI Engine — bổ sung rất mạnh cho dashboard | Nội dung |
|---|---|
| Việc | bộ nhớ đệm trong RAM cho BigQuery |
| Trong suốt | không đổi truy vấn, không đổi công cụ |
| Hợp với | Looker Studio, Connected Sheets, dashboard |
| Cấu hình | mua dung lượng theo GB |
| Kết hợp | materialized view + BI Engine cho hiệu quả cao nhất |
| Kiểm soát chi phí cho 100 nhà phân tích | Cách |
|---|---|
maximum_bytes_billed mặc định |
trần cho mỗi truy vấn |
| Custom quota theo người dùng | trần theo ngày |
| Reservation với slot | chi phí ĐOÁN TRƯỚC ĐƯỢC thay vì theo byte |
| Materialized view | giảm khối lượng thật |
| Đào tạo | tránh SELECT *, luôn lọc theo phân vùng |
| Theo dõi | INFORMATION_SCHEMA.JOBS — ai tốn nhất |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | BigQuery có dùng view không | Execution details — xem có nhắc tới materialized view | | View còn tươi không | SELECT * FROM <dataset>.INFORMATION_SCHEMA.MATERIALIZED_VIEWS | | Chi phí làm mới bao nhiêu | INFORMATION_SCHEMA.JOBS, lọc job làm mới |
Và một hướng đáng cân nhắc song song với materialized view khi chi phí đã trở nên khó lường với 100 người dùng: chuyển sang mô hình slot (reservation). Nó biến hoá đơn từ "theo byte quét, phụ thuộc việc ai gõ gì" thành một con số cố định hằng tháng — và với quy mô bốn phòng ban truy vấn liên tục, đó thường vừa rẻ hơn vừa dễ lập ngân sách hơn.
A new data engineer needs to be able to create and manage Dataproc jobs and clusters in a specific project. However, following the principle of least privilege, they should not have permissions to access or modify other Google Cloud resources like BigQuery datasets or Cloud SQL instances.
Which predefined IAM role should you grant them at the project level?
- A Dataproc Worker
- B Compute Admin
- C Dataproc Editor
- D Project Editor
Xem giải thích
Đáp án
C — Dataproc Editor (roles/dataproc.editor).
Vì sao đúng
Đề cần toàn quyền tạo và quản lý cụm cùng job Dataproc, nhưng KHÔNG có quyền trên BigQuery, Cloud SQL hay tài nguyên khác. Vai trò định sẵn của chính dịch vụ Dataproc là mức vừa đủ.
⚠ Điểm mấu chốt — vai trò theo DỊCH VỤ giới hạn phạm vi:
roles/dataproc.editor
↓
CÓ:
tạo, sửa, xoá CỤM
nộp, huỷ, xem JOB
quản lý workflow template
autoscaling policy
↓
KHÔNG CÓ:
quyền nào trên BigQuery
quyền nào trên Cloud SQL
quyền IAM
↓
⚠ Đúng ranh giới đề yêu cầu
⚠ Các vai trò của Dataproc:
roles/dataproc.viewer
→ chỉ xem cụm và job
roles/dataproc.editor ← đề này
→ tạo và quản lý cụm, job
roles/dataproc.admin
→ thêm quyền IAM trên tài nguyên Dataproc
roles/dataproc.worker
→ ⚠ dành cho SERVICE ACCOUNT của VM
trong cụm, KHÔNG dành cho người
⚠ Nhưng để cụm chạy được, cần thêm hai thứ:
1. roles/iam.serviceAccountUser
→ trên service account mà CỤM sẽ chạy dưới
→ thiếu là KHÔNG TẠO ĐƯỢC cụm
2. Quyền trên DỮ LIỆU
→ job Spark đọc GCS → storage.objectViewer
→ ghi BigQuery → bigquery.dataEditor
↓
⚠ Nhưng đề nói rõ KHÔNG cho quyền
BigQuery → nên trong phạm vi câu hỏi,
dataproc.editor là đáp án
Xem thêm câu #12995 (cùng lô) và #12952, #12956, #12957, #12975 (lô 134): cùng họ câu hỏi quyền tối thiểu. Quy tắc chung: vai trò ĐỊNH SẴN của chính dịch vụ, cấp ở PHẠM VI hẹp nhất.
Vì sao các phương án khác sai
-
B (Compute Admin) — đây là phương án gần nhất vì cụm Dataproc chạy trên VM Compute Engine, nhưng nó cho toàn quyền trên MỌI VM trong project, kể cả những máy không liên quan tới Dataproc — quá rộng.
-
A (Dataproc Worker) — vai trò dành cho service account của chính các VM trong cụm, không phải cho người dùng; nó không cho phép tạo cụm.
-
D (Project Editor) — rộng một cách nguy hiểm: sửa được gần như mọi tài nguyên, kể cả BigQuery và Cloud SQL mà đề cấm.
Ghi nhớ
⚠ Các vai trò Dataproc — bảng phải thuộc: | Vai trò | Dành cho | |---|---| | roles/dataproc.viewer | chỉ xem | | roles/dataproc.editor | tạo và quản lý cụm, job | | roles/dataproc.admin | + quản lý IAM của tài nguyên Dataproc | | roles/dataproc.worker | SERVICE ACCOUNT của VM trong cụm | | Bẫy | worker không phải vai trò cho người dùng |
Từ khoá nhận diện:
"quản lý cụm và job Dataproc, không đụng gì khác" →
dataproc.editor"service account của VM trong cụm" →dataproc.worker"toàn quyền VM" →compute.admin— quá rộng "Project Editor cho nhanh" → luôn sai trong câu hỏi quyền tối thiểu "gắn service account cho cụm" →iam.serviceAccountUser
| Hai bộ quyền mà cụm Dataproc cần | Bộ |
|---|---|
| Quyền của NGƯỜI tạo cụm | dataproc.editor + iam.serviceAccountUser |
| Quyền của SERVICE ACCOUNT cụm chạy dưới | dataproc.worker + quyền trên dữ liệu |
| Ví dụ quyền dữ liệu | storage.objectViewer, bigquery.dataEditor |
| Bẫy thường gặp | cấp đủ cho người, quên cấp cho service account của cụm |
| Triệu chứng | cụm tạo được nhưng job thất bại vì thiếu quyền đọc dữ liệu |
| Vì sao không nên dùng service account mặc định | Nội dung |
|---|---|
| Compute Engine default SA | có roles/editor |
| Nghĩa là | job Spark chạy với quyền sửa gần như mọi thứ |
| Nên | tạo service account riêng cho cụm |
| Cấp | dataproc.worker + đúng quyền dữ liệu cần |
| Chặn mặc định | Organization Policy automaticIamGrantsForDefaultServiceAccounts |
| Nguyên tắc chọn vai trò trong câu hỏi thi | Nguyên tắc |
|---|---|
| Ưu tiên vai trò ĐỊNH SẴN của chính dịch vụ | dataproc.*, bigquery.*, storage.* |
| Tránh vai trò cơ bản | Owner, Editor, Viewer |
| Tránh vai trò của dịch vụ KHÁC | compute.admin cho Dataproc |
| Chú ý PHẠM VI | project, dataset, bucket, hay tài nguyên đơn lẻ |
| Nhận diện vai trò dành cho MÁY | *.worker, *.agent |
| Rà soát quyền định kỳ | Công cụ |
|---|---|
| IAM Recommender | gợi ý hạ vai trò không dùng tới |
| Policy Analyzer | ai có quyền gì ở đâu |
| Cloud Asset Inventory | ảnh chụp toàn bộ |
| Audit log | ai thực sự làm gì |
| Nhịp độ | mỗi quý và khi có thay đổi nhân sự |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | Người này có vai trò gì | gcloud projects get-iam-policy <id> | | Vai trò gồm permission nào | gcloud iam roles describe roles/dataproc.editor | | Vì sao tạo cụm thất bại | Policy Troubleshooter — thường thiếu serviceAccountUser |
Và một lỗi cấu hình gần như chắc chắn sẽ gặp trong lần tạo cụm đầu tiên: thiếu roles/iam.serviceAccountUser. Kỹ sư có đủ quyền Dataproc nhưng vẫn không tạo được cụm, và thông báo lỗi nói về service account chứ không nói về Dataproc — nên rất dễ dẫn người ta đi cấp thêm quyền Dataproc mà mãi không hết lỗi.
A team is building an analytical data pipeline that processes terabytes of structured data. The final output will be stored in Cloud Storage and queried frequently by BigQuery.
To optimize query performance and minimize the amount of data scanned by BigQuery, which data format should they choose for the output files?
- A JSON
- B Apache Parquet
- C CSV
- D XML
Xem giải thích
Đáp án
B — Apache Parquet.
Vì sao đúng
Đề nêu hai mục tiêu: tối ưu hiệu năng truy vấn và giảm tối đa lượng dữ liệu BigQuery phải QUÉT. Định dạng lưu theo CỘT là cách trực tiếp nhất để đạt cả hai.
⚠ Điểm mấu chốt — lưu theo cột nghĩa là đọc ít hơn:
Bảng có 50 cột, truy vấn cần 3 cột
↓
LƯU THEO DÒNG (CSV, JSON, Avro)
↓
→ phải đọc CẢ 50 cột của mọi dòng
rồi mới bỏ đi 47 cột
LƯU THEO CỘT (Parquet)
↓
→ chỉ đọc ĐÚNG 3 cột
↓
⚠ BigQuery tính tiền theo BYTE QUÉT
→ đọc ít hơn = RẺ HƠN và NHANH HƠN
⚠ Parquet còn có hai cơ chế cắt dữ liệu nữa:
ROW GROUP + THỐNG KÊ min/max
↓
Mỗi row group ghi sẵn min/max của từng cột
↓
WHERE gia > 1000000
↓
→ bỏ qua HẲN row group có max < 1000000
→ gọi là PREDICATE PUSHDOWN
NÉN THEO CỘT
↓
Cùng một cột = cùng kiểu, giá trị lặp nhiều
↓
→ mã hoá từ điển, run-length rất hiệu quả
→ tệp nhỏ hơn nhiều lần so với CSV/JSON
⚠ So bốn định dạng cho đúng bài toán này:
PARQUET → cột, nén tốt, pushdown ← tối ưu nhất
ORC → cũng theo cột, tương đương
AVRO → theo DÒNG, tốt cho NẠP và truyền tin,
kém hơn cho quét chọn lọc
JSON → văn bản, cồng kềnh, phân tích chậm
CSV → tệ nhất: không kiểu, không nén,
không pushdown
XML → còn cồng kềnh hơn JSON
Xem thêm câu #12950 (lô 134): khoá Avro vì đề ở đó mô tả theo DÒNG, lược đồ nhúng, tiến hoá lược đồ. Và #12960 (lô 134): khoá JSON vì mô tả
{}lồng nhau. Ba câu, ba khoá, phân biệt bằng chính đặc điểm được mô tả — hoàn toàn nhất quán.
Vì sao các phương án khác sai
-
A (JSON) — đây là phương án gần nhất trong nhóm còn lại vì giữ được cấu trúc lồng nhau, nhưng nó là văn bản, lưu theo dòng, cồng kềnh (lặp tên khoá mọi bản ghi) và không có predicate pushdown.
-
C (CSV) — không có kiểu dữ liệu, nén kém, không pushdown; định dạng tệ nhất cho phân tích quy mô lớn.
-
D (XML) — cồng kềnh hơn cả JSON, và BigQuery không hỗ trợ nạp trực tiếp.
Ghi nhớ
⚠ Định dạng theo mục đích — bảng phải thuộc: | Mục đích | Định dạng | |---|---| | PHÂN TÍCH, đọc chọn lọc cột | Parquet, ORC | | NẠP dữ liệu, truyền tin, tiến hoá lược đồ | Avro | | Trao đổi với API, dữ liệu lồng linh hoạt | JSON | | Trao đổi đơn giản, phổ biến | CSV | | Bảng có ACID trên data lake | Iceberg, Delta, Hudi |
Từ khoá nhận diện:
"BigQuery truy vấn tệp trong GCS, giảm byte quét" → Parquet "theo dòng, lược đồ nhúng, tiến hoá" → Avro "
{}lồng nhau, đọc được bằng mắt" → JSON "mở bằng Excel" → CSV "nạp nhanh nhất vào BigQuery" → Avro hoặc Parquet
| Ba cơ chế giúp Parquet quét ít | Cơ chế |
|---|---|
| Column pruning | chỉ đọc cột cần |
| Predicate pushdown | bỏ qua row group nhờ thống kê min/max |
| Nén theo cột | từ điển, run-length, delta |
| Kết quả | quét ít hơn CSV nhiều lần |
| Với BigQuery external/BigLake table | tiết kiệm trực tiếp thành tiền |
| Thiết kế tệp Parquet cho tốt | Thói quen |
|---|---|
| Kích thước tệp 128 MB – 1 GB | tránh hàng vạn tệp nhỏ |
| Row group vài trăm MB | cân bằng giữa pushdown và chi phí |
| SẮP XẾP theo cột hay lọc | thống kê min/max mới hiệu quả |
| Phân vùng theo thư mục | nam=2026/thang=09/ — Hive partitioning |
| Nén Snappy hoặc ZSTD | cân bằng tốc độ và tỉ lệ nén |
| Vấn đề "quá nhiều tệp nhỏ" | Nội dung |
|---|---|
| Triệu chứng | truy vấn chậm bất thường dù dữ liệu không lớn |
| Nguyên nhân | chi phí liệt kê và mở tệp lớn hơn chi phí đọc |
| Khắc phục | gộp tệp định kỳ (compaction) |
| Với BigLake | bật metadata caching |
| Phòng ngừa | ngưỡng dung lượng khi ghi, không ghi theo micro-batch quá nhỏ |
| Nếu dữ liệu truy vấn RẤT thường xuyên | Cân nhắc |
|---|---|
| NẠP hẳn vào bảng BigQuery | hiệu năng tốt nhất |
| BigLake table trên Parquet | tại chỗ, có bảo mật chi tiết |
| External table thường | đơn giản nhất, ít tính năng nhất |
| So sánh | bảng quản lý > BigLake > external về hiệu năng |
| Đề này | giữ ở GCS nhưng truy vấn nhiều → Parquet là bắt buộc |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | Truy vấn quét bao nhiêu | --dry_run, và total_bytes_billed | | Tệp có quá nhỏ không | gcloud storage ls -l xem phân bố kích thước | | Lược đồ Parquet thế nào | parquet-tools schema, hoặc bq show trên external table |
Và một chi tiết ảnh hưởng tới hiệu năng nhiều hơn người ta tưởng: sắp xếp dữ liệu theo cột hay lọc trước khi ghi Parquet. Thống kê min/max của mỗi row group chỉ giúp bỏ qua dữ liệu khi các giá trị gần nhau nằm cùng chỗ — với dữ liệu ghi theo thứ tự ngẫu nhiên, mọi row group đều chứa đủ dải giá trị, và predicate pushdown gần như mất tác dụng.
You are building an application on Compute Engine that needs to read data from a Cloud Storage bucket. You want to follow Google's recommended best practice for authenticating the application to the Cloud Storage API securely, without managing and distributing static credential files.
What should you do?
- A Assign the required IAM roles directly to the Compute Engine VM's service account.
- B Store a service account key in Cloud Storage and have the application download it on startup.
- C Create a service account, download its JSON key, and embed it in the application's source code.
- D Allow unauthenticated access to the Cloud Storage bucket.
Xem giải thích
Đáp án
A — Gán các vai trò IAM cần thiết TRỰC TIẾP cho service account của VM Compute Engine.
Vì sao đúng
Đây là thực hành được Google khuyến nghị: VM có sẵn một danh tính, và ứng dụng lấy token qua metadata server — không cần tệp khoá nào.
⚠ Điểm mấu chốt — token đến từ metadata server, không từ tệp:
VM chạy dưới một SERVICE ACCOUNT
↓
Ứng dụng gọi thư viện client
(không cấu hình gì thêm)
↓
Thư viện tự hỏi METADATA SERVER
metadata.google.internal
↓
Nhận ACCESS TOKEN ngắn hạn
↓
⚠ Token TỰ HẾT HẠN và TỰ LÀM MỚI
⚠ KHÔNG có tệp khoá nào trên đĩa
⚠ KHÔNG có gì để rò rỉ
⚠ Application Default Credentials — vì sao mã không phải đổi:
Thư viện client tìm thông tin xác thực
theo thứ tự:
1. GOOGLE_APPLICATION_CREDENTIALS
2. Thông tin của gcloud (máy dev)
3. METADATA SERVER (trên GCP) ← ở đây
↓
→ cùng một đoạn mã chạy được
trên máy dev lẫn trên VM
→ không có nhánh if nào cho xác thực
⚠ Vì sao khoá JSON là thứ nên tránh:
Khoá service account dạng JSON
↓
⚠ KHÔNG TỰ HẾT HẠN
⚠ Dễ lọt vào Git, ảnh container, log
⚠ Sao chép được, không truy vết được
⚠ Rò rỉ = kẻ khác dùng vô thời hạn
↓
Nhúng khoá vào MÃ NGUỒN là tệ nhất
→ khoá đi theo mọi bản sao kho mã
↓
Organization Policy có ràng buộc
disableServiceAccountKeyCreation
để CHẶN HẲN việc tạo khoá
Xem thêm câu #12568 (lô 133) về gắn service account cho VM, và #12975 (lô 134) về cấp quyền tối thiểu cho service account. Ba câu mô tả ba phần của cùng một thực hành.
Vì sao các phương án khác sai
-
B (lưu khoá trong Cloud Storage rồi tải về lúc khởi động) — đây là phương án gần nhất vì ít tệ hơn việc nhúng vào mã, nhưng nó vẫn tạo ra một tệp khoá tồn tại lâu dài, và còn thêm bài toán "ai được đọc bucket chứa khoá". Hoàn toàn không cần thiết khi VM đã có danh tính.
-
C (nhúng khoá JSON vào mã nguồn) — tệ nhất: khoá vào Git, vào mọi bản sao, vào ảnh container.
-
D (mở quyền truy cập công khai cho bucket) — lỗ hổng bảo mật nghiêm trọng; ai trên Internet cũng đọc được.
Ghi nhớ
⚠ Xác thực trên Google Cloud — thứ tự ưu tiên: | Môi trường | Cách xác thực | |---|---| | Chạy TRÊN Google Cloud | service account gắn sẵn + metadata server | | Chạy ngoài GCP (AWS, on-prem, CI) | Workload Identity Federation | | Trong GKE | Workload Identity cho pod | | Máy dev cá nhân | gcloud auth application-default login | | Khoá JSON | PHƯƠNG ÁN CUỐI CÙNG, nên tránh hẳn |
Từ khoá nhận diện:
"ứng dụng trên VM gọi API Google" → service account gắn cho VM "ứng dụng chạy ngoài GCP" → Workload Identity Federation "pod GKE gọi API Google" → Workload Identity "tải khoá JSON về" → gần như luôn là phương án SAI "mở công khai cho tiện" → luôn sai
| Workload Identity Federation — thay thế khoá JSON | Nội dung |
|---|---|
| Việc | cho phép danh tính NGOÀI GCP mạo danh service account |
| Nguồn hỗ trợ | AWS, Azure, GitHub Actions, OIDC bất kỳ |
| Lợi ích | KHÔNG có khoá dài hạn nào |
| Dùng cho | CI/CD, ứng dụng đa đám mây |
| Khuyến nghị | thay thế mọi khoá JSON còn lại |
| Scope ↔ IAM trên VM — bẫy kinh điển | Nội dung |
|---|---|
| Scope | lớp CŨ, giới hạn ở mức VM |
| IAM role | lớp quyết định quyền thật |
| Quyền hiệu lực | GIAO của hai lớp |
| Khuyến nghị | --scopes=cloud-platform rồi siết bằng IAM |
| Triệu chứng khi sai | 403 dù IAM đã đủ — vì scope hẹp |
| Thực hành tốt với service account của VM | Thói quen |
|---|---|
| KHÔNG dùng Compute Engine default SA | nó mang roles/editor |
| Mỗi ứng dụng một service account riêng | |
| Cấp vai trò hẹp nhất, ở phạm vi hẹp nhất | bucket, không phải project |
--scopes=cloud-platform |
rồi siết bằng IAM |
| Chặn tạo khoá | Organization Policy |
| Rà soát | IAM Recommender |
| Nếu buộc phải dùng khoá JSON | Biện pháp |
|---|---|
| Lưu trong Secret Manager, không trong Git | |
| Đặt hạn xoay khoá | và thực sự xoay |
| Giới hạn quyền tối đa | khoá lộ thì thiệt hại nhỏ |
| Theo dõi việc sử dụng | audit log |
| Có kế hoạch chuyển sang WIF | đây chỉ là giải pháp tạm |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | VM đang chạy dưới SA nào | gcloud compute instances describe <vm> --format="value(serviceAccounts)" | | Trong VM lấy được token không | curl -H "Metadata-Flavor: Google" metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token | | Có khoá JSON nào còn tồn tại | gcloud iam service-accounts keys list --iam-account=<sa> |
Và một việc rà soát nên làm ngay trong tuần này ở bất kỳ project nào đã chạy được vài năm: liệt kê toàn bộ khoá service account đang tồn tại. Những khoá tạo ra để "thử cho nhanh" rồi bị quên là loại tài sản nguy hiểm nhất trong một dự án đám mây — chúng không hết hạn, không ai theo dõi, và thường vẫn còn đủ quyền để làm rất nhiều việc.
A manufacturing company needs to collect daily production logs from an on-premises SFTP server and store them in a Cloud Storage bucket located in europe-west3 (Frankfurt). Due to data residency requirements, the data processing and transfer management must also occur within the European Union.
Which solution meets all these requirements?
- A Use Transfer Appliance to ship the data from the data center to Google Cloud.
- B Use gsutil on the on-premises server to run a nightly script to copy the files.
- C Use Storage Transfer Service with its default settings to transfer from the SFTP server.
- D Use Storage Transfer Service, configuring it to use a transfer agent pool located in an EU region.
Xem giải thích
Đáp án
D — Dùng Storage Transfer Service, cấu hình transfer agent pool đặt tại một Region của EU.
Vì sao đúng
Đề có hai ràng buộc chồng lên nhau: lấy dữ liệu từ SFTP tại chỗ (nên phải dùng agent), và cả việc XỬ LÝ lẫn QUẢN LÝ truyền tải cũng phải nằm trong EU.
⚠ Điểm mấu chốt — agent pool có VỊ TRÍ, và vị trí đó quan trọng:
Storage Transfer Service cho nguồn TẠI CHỖ
↓
Cần AGENT chạy gần hệ thống nguồn
(container Docker trên máy chủ của bạn)
↓
Agent thuộc một AGENT POOL
↓
⚠ Agent pool có REGION
→ quyết định dữ liệu được ĐIỀU PHỐI
và XỬ LÝ ở đâu
↓
Đặt pool ở EU → toàn bộ luồng
nằm trong EU
⚠ Vì sao "cấu hình mặc định" chưa đủ:
Storage Transfer Service mặc định
↓
⚠ Có thể dùng tài nguyên điều phối
ngoài EU
↓
→ dữ liệu đích ở europe-west3 thì đúng,
nhưng phần XỬ LÝ và QUẢN LÝ
có thể vượt ranh giới
↓
⚠ Chính sách trong đề nói rõ
cả hai phần đó cũng phải trong EU
⚠ Kiến trúc đầy đủ để tuân thủ:
Agent pool ở EU
+ Bucket đích ở europe-west3
+ Organization Policy gcp.resourceLocations
giới hạn ở các Region EU/Đức
+ VPC Service Controls (nếu cần vành đai)
↓
→ dữ liệu và mọi thao tác quản lý
đều nằm trong EU
Xem thêm câu #12933 (lô 134): cũng khoá Storage Transfer Service, nhưng nguồn là Amazon S3 nên không cần agent. Và #12964 (lô 134): chọn region cụ thể cho chủ quyền dữ liệu. Ba câu bổ sung nhau — nhất quán.
Vì sao các phương án khác sai
-
C (Storage Transfer Service với cấu hình mặc định) — đây là phương án gần nhất và đúng dịch vụ, nhưng nó không bảo đảm phần điều phối nằm trong EU — chính điều mà chính sách trong đề đòi hỏi.
-
B (chạy
gsutilbằng script hằng đêm) — không phải dịch vụ được quản lý: không tự thử lại, không kiểm tra toàn vẹn, không báo cáo, phải tự vận hành. -
A (Transfer Appliance) — thiết bị vật lý cho khối lượng rất lớn một lần; nhật ký sản xuất hằng ngày cần một luồng liên tục, không phải gửi ổ cứng qua bưu điện.
Ghi nhớ
⚠ Storage Transfer Service — hai chế độ nguồn: | Nguồn | Cần agent? | |---|---| | Amazon S3, Azure Blob, HTTP/HTTPS | KHÔNG — Google kéo trực tiếp | | Cloud Storage khác | KHÔNG | | Hệ thống tệp tại chỗ, SFTP/POSIX | CÓ — cần agent pool | | Agent chạy bằng | container Docker trên máy chủ của bạn | | Agent pool có REGION | quyết định nơi điều phối |
Từ khoá nhận diện:
"nguồn tại chỗ + ràng buộc vùng" → STS với agent pool đúng Region "S3 → GCS" → STS, không cần agent "hàng trăm TB, mạng kém" → Transfer Appliance "dữ liệu phải ở trong nước" → region cụ thể + Organization Policy "script gsutil hằng đêm" → không phải giải pháp được quản lý
| Agent pool — điều cần nhớ | Nội dung |
|---|---|
| Nhóm các agent làm việc cùng nhau | |
| Có REGION | ảnh hưởng nơi điều phối và tuân thủ |
| Nhiều agent trong một pool | tăng thông lượng, chịu lỗi |
| Giới hạn băng thông | đặt được để không nghẽn mạng văn phòng |
| Chạy agent | docker run với thông tin xác thực service account |
| Theo dõi | trạng thái agent trong console |
| Ba lớp bảo đảm chủ quyền dữ liệu | Lớp |
|---|---|
| Chọn Region cụ thể cho mọi tài nguyên | bucket, dataset, agent pool |
Organization Policy gcp.resourceLocations |
CHẶN tạo tài nguyên ngoài vùng |
| VPC Service Controls | vành đai chống dữ liệu ra ngoài |
| CMEK với key ring trong vùng | nếu cần tự quản khoá |
| Assured Workloads | gói tuân thủ có sẵn cho EU |
| Đừng quên các dịch vụ phụ trợ | Dịch vụ |
|---|---|
| Cloud Logging | log bucket cũng có Region |
| Cloud Monitoring | dữ liệu chỉ số |
| Sao lưu | --backup-location |
| Dịch vụ xử lý | Dataflow, Dataproc, Cloud Run — đều phải khai Region |
| Rà soát | Cloud Asset Inventory, lọc theo vị trí |
| STS — tính năng đáng dùng | Tính năng |
|---|---|
| Chạy theo LỊCH | đồng bộ hằng ngày |
| Chỉ chuyển tệp MỚI hoặc ĐÃ ĐỔI | so theo thời gian sửa và checksum |
| Xoá ở nguồn sau khi chuyển | tuỳ chọn |
| Lọc theo tiền tố | chuyển một phần |
| Thông báo qua Pub/Sub | tự động hoá bước tiếp theo |
| Báo cáo lỗi | biết tệp nào không chuyển được |
Ba việc kiểm chứng: | Việc | Cách | |---|---| | Agent pool ở Region nào | console → Storage Transfer → Agent pools | | Agent có đang chạy không | trạng thái agent, và docker ps trên máy chủ | | Tệp đã sang đủ chưa | so số tệp và dung lượng hai bên |
Và một chi tiết dễ bị bỏ qua khi lập kế hoạch tuân thủ: vị trí của agent pool là một quyết định về chủ quyền dữ liệu, không chỉ là một tuỳ chọn kỹ thuật. Bucket đích đặt đúng ở Frankfurt vẫn có thể không đủ nếu phần điều phối truyền tải diễn ra ở nơi khác — và đó chính là chi tiết phân biệt hai phương án gần giống nhau trong câu hỏi này.