Heap Table vs Clustered Index

Hai cách database lưu dữ liệu trên disk - ảnh hưởng trực tiếp đến cách chọn primary key và thiết kế schema.

Heap Table (PostgreSQL mặc định)

Dữ liệu append vào cuối file, không quan tâm thứ tự. Insert PK=999 trước PK=1 cũng được. Tất cả index (kể cả primary key) đều lưu địa chỉ vật lý (tuple ID / ctid) của row.

INDEX (email)                    TABLE (heap)
alice@ → row ở page 5    ──→    Page 5: [alice, 28, ...]
bob@   → row ở page 2    ──→    Page 2: [bob, 35, ...]

Điểm quan trọng: mọi index đều “bình đẳng” - lookup bằng PK hay secondary index đều cần đúng 1 bước nhảy từ index vào table.

Clustered Index (MySQL/InnoDB mặc định)

Primary key chính là bảng: dữ liệu row được lưu ngay trong leaf node của PK index, sắp xếp theo thứ tự PK. Không có “bảng heap” riêng. Secondary index không trỏ đến vị trí vật lý mà trỏ đến giá trị primary key → lookup qua secondary index = 2 bước (tìm PK trong secondary index → tìm row trong PK index).

So sánh

Heap Table (PostgreSQL)Clustered Index (MySQL)
PK lookup2 bước: PK index → heap1 bước: PK index = table
Secondary lookup2 bước: sec. index → heap2 bước: sec. index → PK index
Insert random PKNhanh (append vào heap)Chậm (insert đúng vị trí sorted)
PK size ảnh hưởngÍtNhiều (PK copy vào MỌI secondary index)

3 hệ quả thực tế cho MySQL (Clustered Index)

  1. KHÔNG dùng UUIDv4 làm primary key - mỗi row mới insert vào vị trí random trong tree; bảng lớn không fit RAM → insert chậm gấp 3-10 lần so với auto-increment. Xem Primary Key và thứ tự Insert.
  2. PK size ảnh hưởng toàn bộ database - PK value được copy vào mỗi secondary index entry: 1 triệu row × 5 index, PK BIGINT (8 bytes) = 40 MB overhead; PK ULID string (26 bytes) = 130 MB. Với 50 bảng → chênh 4.5 GB = khác biệt giữa “fit RAM” và “phải đọc disk”.
  3. PK lookup cực nhanh → tận dụng cho CRUD apps - data có sẵn ngay khi tìm thấy PK entry. Đây là lý do MySQL/InnoDB phổ biến cho web application.

Liên quan