0

Greenplum Database Bài học 9: Chiến lược phân phối dữ liệu (Distribution Strategies): Trái tim của hiệu năng Greenplum

Sau khi đã làm chủ nền tảng kiến trúc MPP và cách vận hành cụm ở Phần 1, chúng ta bước sang Phần 2: Học cách thiết kế cấu trúc lưu trữ dữ liệu bên trong Greenplum.

Nếu trong cơ sở dữ liệu đơn lẻ (như PostgreSQL hay MySQL), việc thiết kế bảng chỉ đơn giản là chọn kiểu dữ liệu và đánh Index, thì trong một hệ thống MPP như Greenplum, câu hỏi quan trọng nhất khi tạo bảng không phải là "Cột này kiểu gì?", mà là:

"Làm thế nào để rải 1 tỷ dòng dữ liệu này xuống các Segments sao cho hoàn toàn cân bằng?"

Quyết định đó nằm ở Chiến lược phân phối dữ liệu (Distribution Strategies) — được định nghĩa bằng mệnh đề DISTRIBUTED BY (...) hoặc DISTRIBUTED R/REPLICATED. Đây chính là trái tim quyết định 80% hiệu năng của mọi câu truy vấn trên Greenplum.

1. Bản chất của mệnh đề DISTRIBUTED BY trong Greenplum

Khi bạn tạo một bảng mới trên Greenplum mà không chỉ định rõ quy tắc phân phối, Greenplum sẽ tự động chọn một chiến lược mặc định (thường là băm cột đầu tiên của bảng).

Tuy nhiên, việc để hệ thống tự quyết định hoặc chọn sai cột phân phối là nguyên nhân số 1 dẫn đến thảm họa "treo hệ thống" do lệch dữ liệu (Data Skew).

Greenplum hỗ trợ 3 chiến lược phân phối dữ liệu chính:

┌────────────────────────────────────────────────────────────────────────┐
│                        3 CHIẾN LƯỢC PHÂN PHỐI DỮ LIỆU                    │
└───────────────────┬───────────────────┬────────────────────────────────┘
                    │                   │
         1. HASH DISTRIBUTION      2. RANDOM DISTRIBUTION     3. REPLICATED DISTRIBUTION
         (DISTRIBUTED BY (col))    (DISTRIBUTED RANDOMLY)     (DISTRIBUTED REPLICATED)
                    │                   │                            │
            Băm giá trị cột           Rải ngẫu nhiên               Copy toàn bộ 100%
            để đưa vào Segment        vào các Segments             xuống TẤT CẢ Segments
            cố định (Tối ưu Join)     (Ghi nhanh, Join kém)        (Dành cho bảng Danh mục nhỏ)

2. Chi tiết 3 Chiến lược phân phối dữ liệu

2.1. Hash Distribution (DISTRIBUTED BY (column_name)) — "Vua của hiệu năng"

Đây là chiến lược được khuyên dùng cho 90% các bảng dữ liệu lớn (Fact Tables) trong Data Warehouse.

  • Cơ chế hoạt động: Greenplum lấy giá trị của cột được chọn (column_name), đưa qua hàm băm (Hash Function) để tính ra một mã số định danh, từ đó quyết định chính xác dòng dữ liệu đó phải được ghi vào Segment nào.

  • Đặc tính tuyệt vời:

    • Các dòng có cùng giá trị của cột phân phối (ví dụ: cùng một user_id hoặc store_id) sẽ luôn luôn nằm trên cùng một Segment.

    • Khi bạn thực hiện phép JOIN hai bảng lớn dựa trên cùng một khóa phân phối (user_id), Greenplum không cần phải di chuyển dữ liệu qua mạng (Interconnect). Phép tính JOIN diễn ra cục bộ ngay bên trong từng Segment với tốc độ cực thần tốc (gọi là Co-located Join).

  • Quy tắc chọn cột Hash Key:

    • Chọn cột có độ phân tán cao (High Cardinality) như user_id, transaction_id, order_id.

    • Tuyệt đối không chọn các cột có giá trị tập trung hoặc có giá trị NULL chiếm đa số (ví dụ: cột gender chỉ có Nam/Nữ, hoặc cột status chỉ có vài trạng thái). Nếu chọn cột gender, toàn bộ dữ liệu sẽ dồn sạch vào đúng 2 Segment, các Segment còn lại ngồi chơi — dẫn đến hiện tượng Data Skew.

2.2. Random Distribution (DISTRIBUTED RANDOMLY) — "Giải pháp chữa cháy"

  • Cơ chế hoạt động: Greenplum dùng thuật toán xoay vòng (Round-Robin) để rải lần lượt từng dòng dữ liệu mới vào các Segments một cách ngẫu nhiên.

  • Ưu điểm: Đảm bảo dữ liệu luôn luôn được chia đều 100% cho tất cả các Segments, triệt tiêu hoàn toàn hiện tượng lệch dữ liệu lưu trữ (Data Skew). Rất tối ưu khi nạp dữ liệu thô (Staging tables) vào hệ thống.

  • Nhược điểm chí mạng: Vì dữ liệu bị vứt ngẫu nhiên khắp nơi, khi bạn thực hiện câu lệnh JOIN bảng này với bảng khác, Greenplum buộc phải dùng toán tử Redistribute Motion để lật tung mạng nội bộ, bắn dữ liệu chéo qua lại giữa các máy chủ. Điều này làm giảm hiệu năng truy vấn đi rất nhiều. Chỉ dùng DISTRIBUTED RANDOMLY khi bảng không có khóa tự nhiên nào thích hợp để Hash hoặc là bảng Log tạm thời.

2.3. Replicated Distribution (DISTRIBUTED REPLICATED) — "Vũ khí cho bảng nhỏ"

  • Cơ chế hoạt động: Toàn bộ dữ liệu của bảng sẽ được nhân bản và copy nguyên văn 100% xuống tất cả các Segments trong cụm.

  • Ứng dụng thực tế: Dành cho các bảng danh mục nhỏ (Dimension Tables) ít khi thay đổi dữ liệu nhưng thường xuyên bị đem ra JOIN với các bảng giao dịch lớn (Fact Tables), ví dụ: bảng danh mục tỉnh thành (provinces), bảng danh mục loại sản phẩm (categories có vài chục dòng).

  • Lợi ích: Khi Fact Table ở mọi Segment cần tra cứu tên tỉnh thành, nó không cần phải đi hỏi các Segment khác qua mạng, vì bản thân Segment đó đã lưu sẵn một bản sao của bảng danh mục rồi (Local Join).

  • Cảnh báo: Tuyệt đối không dùng cho bảng lớn. Nếu bạn Replicate một bảng có 100 triệu dòng xuống cụm có 50 Segments, bạn đang lãng phí dung lượng đĩa để lưu tới 5 tỷ dòng dữ liệu trên toàn cụm!

3. Ví dụ thực chiến cú pháp SQL trên Greenplum

Hãy xem cách khai báo các chiến lược phân phối khác nhau khi tạo bảng:

SQL

-- 1. Bảng Giao dịch lớn (Fact Table): Dùng Hash Distribution theo user_id
CREATE TABLE fact_transactions (
    transaction_id BIGINT,
    user_id BIGINT,
    amount NUMERIC(12,2),
    store_id INT,
    created_at TIMESTAMP
) DISTRIBUTED BY (user_id);

-- 2. Bảng Log thô mới nạp (Staging Table): Dùng Random Distribution để nạp cực nhanh
CREATE TABLE staging_raw_logs (
    log_data TEXT,
    ingested_at TIMESTAMP
) DISTRIBUTED RANDOMLY;

-- 3. Bảng Danh mục nhỏ (Dimension Table): Dùng Replicated để tối ưu Join
CREATE TABLE dim_store_types (
    type_id INT,
    type_name VARCHAR(50)
) DISTRIBUTED REPLICATED;

4. Cách phát hiện và chẩn đoán thảm họa Data Skew

Sai lầm lớn nhất của lập trình viên khi mới chuyển từ PostgreSQL sang Greenplum là chọn sai khóa phân phối, dẫn đến Data Skew (lệch dữ liệu).

Bạn có thể chạy câu lệnh SQL hệ thống sau trên Master để kiểm tra xem các bảng của mình có đang bị dồn cục dữ liệu ở một Segment nào không:

SQL

SELECT 
    schemaname,
    tablename,
    c.reltuples AS estimated_rows,
    MAX(s.statis) AS max_segment_rows,
    MIN(s.statis) AS min_segment_rows
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
JOIN (
    SELECT tableoid, gp_segment_id, COUNT(*) AS statis 
    FROM fact_transactions 
    GROUP BY tableoid, gp_segment_id
) s ON s.tableoid = c.oid
WHERE c.relname = 'fact_transactions'
GROUP BY schemaname, tablename, c.reltuples;

  • Dấu hiệu nhận biết: Nếu max_segment_rows lớn hơn gấp đôi min_segment_rows trên một bảng lớn, cụm của bạn đang bị lệch dữ liệu nghiêm trọng và cần phải thiết kế lại khóa phân phối DISTRIBUTED BY.

Tóm tắt Bài học 9

  • Chiến lược phân phối (DISTRIBUTED BY) là yếu tố quan trọng nhất quyết định hiệu năng của bảng trong cơ sở dữ liệu MPP Greenplum.

  • Hash Distribution (DISTRIBUTED BY (col)) tối ưu nhất cho bảng lớn, nhưng đòi hỏi chọn cột có độ phân tán cao và thường dùng để JOIN.

  • Random Distribution (DISTRIBUTED RANDOMLY) giúp rải đều 100% dữ liệu nhưng làm chậm các câu lệnh JOIN.

  • Replicated Distribution (DISTRIBUTED REPLICATED) nhân bản toàn bộ bảng xuống mọi Segment, chỉ dành riêng cho các bảng danh mục nhỏ.

Ở bài học tiếp theo (Bài học 10), chúng ta sẽ đi sâu vào nghệ thuật chọn cột DISTRIBUTED BY (Hash) sao cho chuẩn xác, cách nhận diện các bẫy liên quan đến khóa ngoại và tối ưu hóa tuyệt đối các phép CO-LOCATED JOIN.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí