Skip to content

Index: Vũ khí tối thượng

Nếu database là một cuốn sách dày 1000 trang, thì Index (Chỉ mục) chính là phần Mục lục ở cuối sách. Không có mục lục, bạn phải lật từng trang (Full Table Scan) để tìm tên "Nguyen Van A". Có mục lục, bạn biết ngay "Nguyen Van A" ở trang 582, 583.

Concept: Cấu trúc Index

1. B-Tree (Balanced Tree) - "The King"

99% trường hợp bạn sẽ dùng cái này.

  • Cấu trúc: Cây cân bằng, dữ liệu được sắp xếp.
  • Dùng cho: =, >, <, >=, <=, BETWEEN, IN, LIKE 'abc%'.
  • Độ phức tạp: O(logN). Tìm trong 1 triệu dòng chỉ mất khoảng 2-3 bước nhảy.

2. Hash Index

  • Cấu trúc: Bảng băm (Hash Table).
  • Dùng cho: Chỉ so sánh bằng =. Cực nhanh (O(1)).
  • Hạn chế: Không dùng được cho so sánh khoảng (>, <) hoặc sắp xếp (ORDER BY). Ít phổ biến hơn B-Tree.

Composite Index & The "Leftmost Prefix" Rule

Đây là kiến thức phân biệt Senior và Fresher. Giả sử bạn có Index đa cột: idx_name_age (name, age).

B-Tree sẽ sắp xếp theo name trước, sau đó nếu name trùng nhau thì xếp theo age.

Quy tắc "Trái nhất" (Leftmost Prefix): Index (A, B, C) chỉ có tác dụng nếu bạn query theo:

  1. A
  2. AB
  3. ABC

CÁC TRƯỜNG HỢP INDEX KHÔNG HOẠT ĐỘNG (DEAD):

  1. Chỉ query cột age (Bỏ qua cột đầu name):

    sql
    SELECT * FROM users WHERE age = 25; 
    -- Index idx_name_age VÔ DỤNG! Database phải Scan toàn bộ.

    Lý do: Giống như tìm những người "25 tuổi" trong danh bạ điện thoại (sắp xếp theo Tên). Bạn không thể tìm được nếu không duyệt từ đầu đến cuối.

  2. Bị đứt đoạn: Query WHERE A = 1 AND C = 3. Index chỉ dùng được cho A, phần C phải lọc thủ công.

Khi nào Index KHÔNG hoạt động?

Ngoài quy tắc Leftmost, Index còn bị "vô hiệu hóa" nếu:

  1. Dùng hàm lên cột Index:

    sql
    -- SAI: Index chết
    SELECT * FROM users WHERE YEAR(created_at) = 2024;
    
    -- ĐÚNG:
    SELECT * FROM users WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01';
  2. Dùng toán tử phủ định: <>, !=, NOT IN thường không dùng Index hiệu quả.

  3. LIKE '%keyword': Bắt đầu bằng Wildcard là chết (như đã nói ở bài Filtering).

  4. Data Distribution: Nếu bạn lọc WHERE gender = 'Male' mà 50% dữ liệu là Male, Database sẽ chọn Full Scan cho nhanh thay vì nhảy qua lại Index.