Greenplum Database Bài học 10: DISTRIBUTED BY (Hash): Cách chọn Distribution Key chuẩn xác để tối ưu hóa phép JOIN
Ở Bài học 9, chúng ta đã điểm qua 3 chiến lược phân phối dữ liệu cơ bản và thấy rằng Hash Distribution (DISTRIBUTED BY (col)) là lựa chọn hàng đầu cho các bảng dữ liệu lớn (Fact Tables). Tuy nhiên, việc chọn bừa một cột làm khóa phân phối sẽ không giải quyết được vấn đề — thậm chí còn khiến hiệu năng tồi tệ hơn cả việc dùng Random.
Trong bài học này, chúng ta sẽ mổ xẻ nghệ thuật chọn Distribution Key sao cho chuẩn xác, hiểu sâu về cơ chế Co-located Join và cách triệt tiêu các toán tử dịch chuyển dữ liệu qua mạng (Motion) để đạt tốc độ xử lý hàng triệu bản ghi trong tích tắc.
1. Giải phẫu phép JOIN trong Greenplum: Mạng lưới Interconnect gánh chịu những gì?
Khi bạn thực hiện một câu lệnh JOIN giữa hai bảng lớn (orders và order_items) trong cơ sở dữ liệu đơn lẻ (PostgreSQL), hệ thống chỉ cần quét qua các Index hoặc bộ nhớ RAM của một máy duy nhất.
Nhưng trong kiến trúc Shared-Nothing MPP của Greenplum, nếu hai bảng này được phân phối bởi hai cột khác nhau, thảm họa mạng sẽ xảy ra:
┌────────────────────────────────────────────────────────────────────────┐
│ THẢM HỌA: NON-COOCATED JOIN (Redistribute Motion) │
└───────────────────┬─────────────────────────────────┬──────────────────┘
│ │
┌─────────────────────┐ ┌─────────────────────┐
│ Segment 0 │ │ Segment 1 │
│ Bảng A (Phân phối │ │ Bảng B (Phân phối │
│ theo order_id) │ │ theo customer_id) │
└──────────┬──────────┘ └──────────┬──────────┘
│ │
└───────────► ◄───────────────────┘
(Bắn toàn bộ dữ liệu qua mạng
Interconnect để băm lại Hash)
▼
[ Tắc nghẽn mạng & CPU ]
-
Redistribute Motion (Đổi chỗ toàn bộ dữ liệu): Vì dòng dữ liệu của
orders(băm theoorder_id) vàorder_items(giả sử băm theoproduct_id) nằm ở các Segment hoàn toàn khác nhau, Greenplum buộc phải bật chế độ "bắn phá" mạng Interconnect: băm lại toàn bộ dữ liệu của cả hai bảng và gửi chéo qua lại giữa hàng chục máy chủ trong cụm chỉ để khớp điều kiệnJOIN. -
Kết quả: Thời gian của câu truy vấn bị bóp nghẹt bởi tốc độ của card mạng và băng thông nội bộ.
2. "Chén Thánh" trong Greenplum: Co-located Join (Phép nối cùng vị trí)
Điều gì sẽ xảy ra nếu bạn thiết kế cấu trúc sao cho hai bảng có quan hệ chặt chẽ với nhau được phân phối bởi CÙNG MỘT khóa (Distribution Key)?
Ví dụ: Cả bảng orders và bảng order_items đều được phân phối theo DISTRIBUTED BY (order_id):
-
Điều kỳ diệu xảy ra:
-
Tất cả các dòng đơn hàng mang
order_id = 12345trong bảngordersđược lưu chính xác trên cùng một Segment với các dòng chi tiết sản phẩm mangorder_id = 12345trong bảngorder_items. -
Khi câu lệnh
JOINchạy, không một byte dữ liệu nào phải di chuyển qua mạng Interconnect! -
Mỗi Segment tự thực hiện phép
JOINtrên đúng phần dữ liệu nằm cục bộ trong ổ cứng của chính nó rồi gộp kết quả lại (Co-located Join).
-
| Tiêu chí | Non-Colocated Join (Khác khóa phân phối) | Co-located Join (Cùng khóa phân phối) |
|---|---|---|
| Lưu lượng mạng | Cực kỳ lớn (Phải bắn dữ liệu toàn cụm qua Redistribute Motion). |
Bằng 0 (Xử lý hoàn toàn nội bộ tại từng Segment độc lập). |
| Tài nguyên CPU | Tốn kém cho việc tính toán lại hàm Hash và đồng bộ mạng giữa các nodes. | Tối ưu hóa tối đa, tập trung hoàn toàn cho tính toán logic dữ liệu. |
| Hiệu năng tổng thể | Chậm (Bị thắt cổ chai phụ thuộc vào băng thông Switch mạng). | Cực nhanh (Nhanh gấp hàng chục đến hàng trăm lần). |
3. Ba Quy tắc Vàng khi chọn DISTRIBUTED BY (Hash)
Để chọn được Distribution Key hoàn hảo cho các bảng trong hệ thống Data Warehouse, hãy tuân thủ chặt chẽ 3 nguyên tắc sau:
Quy tắc 1: Chọn cột có độ phân tán cao (High Cardinality)
-
Nguyên tắc: Khóa phân phối phải có số lượng giá trị duy nhất (Distinct Values) lớn và trải đều.
-
Ví dụ tốt:
user_id,transaction_id,device_id,order_uuid. -
Ví dụ tồi:
gender(chỉ có 2-3 giá trị),status(đang xử lý, hoàn thành, hủy),country_code(nếu 99% khách hàng đến từ một quốc gia). Chọn các cột này sẽ tạo ra hiện tượng Data Skew kinh điển — một Segment giữ 99% dữ liệu, các Segment còn lại rảnh rỗi.
Quy tắc 2: Đồng bộ hóa khóa phân phối cho các bảng thường xuyên JOIN (Colocation)
-
Nếu bạn thường xuyên viết câu truy vấn
JOINgiữa bảngorders(Đơn hàng) và bảngpayments(Thanh toán), hãy bắt buộc chọn cùng một cột (ví dụorder_id) làm Distribution Key cho cả hai bảng. -
Đối với quan hệ 1-N (Một đơn hàng có nhiều chi tiết): Hãy chọn khóa chính của bảng cha (
order_id) làm khóa phân phối cho cả bảng cha lẫn bảng con.
Quy tắc 3: Tránh cập nhật cột phân phối (Avoid Updating Distribution Key)
-
Trong cơ sở dữ liệu quan hệ, việc chạy lệnh
UPDATE table SET user_id = 999 WHERE id = 123là chuyện bình thường. -
Nhưng trong Greenplum, nếu bạn đổi giá trị của cột làm Distribution Key, điều đó đồng nghĩa với việc dòng dữ liệu đó phải bị xóa khỏi Segment hiện tại và được chuyển sang một Segment hoàn toàn mới theo quy tắc Hash. Thao tác này cực kỳ tốn chi phí hệ thống. Hãy chọn các cột có giá trị cố định từ khi tạo bản ghi (Immutable Columns) làm khóa phân phối.
4. Trường hợp ngoại lệ: Nên làm gì khi bảng không có khóa tự nhiên tốt?
Đôi khi bạn gặp những bảng dữ liệu không có cột nào có độ phân tán cao, hoặc các cột đều trùng lặp nhiều. Khi đó bạn có 2 hướng giải quyết:
-
Tạo cột nhân tạo (Surrogate Key / Hash Key): Kết hợp 2-3 cột lại với nhau bằng hàm băm hoặc dùng chuỗi UUID làm khóa phân phối.
-
Chấp nhận dùng
DISTRIBUTED RANDOMLY: Nếu bảng đó chỉ là bảng trung gian (Staging table) nạp dữ liệu thô rồi đổ đi ngay, việc phân phối ngẫu nhiên để đảm bảo không bị lệch dữ liệu (Data Skew) quan trọng hơn việc tối ưu hóaJOIN.
Tóm tắt Bài học 10
-
Phép
JOINtrên Greenplum sẽ đạt tốc độ tối đa nếu hai bảng được phân phối cùng một khóa (Co-located Join), giúp loại bỏ hoàn toàn chi phí chuyển dữ liệu qua mạng Interconnect. -
Quy tắc chọn khóa: Chọn cột có độ phân tán cao (High Cardinality), gắn kết các bảng thường xuyên JOIN với nhau và là cột không bao giờ thay đổi giá trị (
Immutable). -
Tránh tuyệt đối các cột có ít giá trị phân loại (như trạng thái, giới tính) làm khóa phân phối để ngăn chặn thảm họa Data Skew.
Ở bài học tiếp theo (Bài học 11), chúng ta sẽ tìm hiểu chi tiết về hai chiến lược còn lại: DISTRIBUTED RANDOMLY vs DISTRIBUTED REPLICATED — khi nào nên dùng, ưu nhược điểm ra sao và những cái giá phải trả.
All Rights Reserved