Giao diện
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:
AAvàBAvàBvàC
CÁC TRƯỜNG HỢP INDEX KHÔNG HOẠT ĐỘNG (DEAD):
Chỉ query cột
age(Bỏ qua cột đầuname):sqlSELECT * 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.
Bị đứt đoạn: Query
WHERE A = 1 AND C = 3. Index chỉ dùng được choA, phầnCphả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:
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';Dùng toán tử phủ định:
<>,!=,NOT INthường không dùng Index hiệu quả.LIKE '%keyword': Bắt đầu bằng Wildcard là chết (như đã nói ở bài Filtering).
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.
🧠 Quiz
Câu 1: Composite Index (a, b, c) có thể tối ưu query nào?
- [ ] A)
WHERE b = 1 AND c = 2(bỏ qua cột a) - [x] B)
WHERE a = 1 AND b = 2(tuân thủ leftmost prefix) - [ ] C)
WHERE c = 1(chỉ cột cuối) - [ ] D) Tất cả query trên đều được tối ưu
💡 Giải thích: B-tree composite index tuân thủ "leftmost prefix rule". Index (a,b,c) hỗ trợ: WHERE a, WHERE a AND b, WHERE a AND b AND c. KHÔNG hỗ trợ WHERE b hoặc WHERE c — phải bắt đầu từ cột trái nhất.
Câu 2: Khi nào Index KHÔNG hiệu quả?
- [ ] A) Khi bảng có nhiều dòng
- [ ] B) Khi dùng với PRIMARY KEY
- [x] C) Khi dùng function trên cột (
WHERE UPPER(name) = 'JOHN'), LIKE bắt đầu bằng %, hoặc cột có selectivity thấp - [ ] D) Khi dùng với JOIN
💡 Giải thích: Function wrap cột thì database không dùng index trên cột đó (dùng functional index nếu cần).
LIKE '%abc'= full scan. Cột với ít giá trị distinct (gender: M/F) thì database chọn full scan nhanh hơn nhảy index.
Câu 3: Covering Index là gì và tại sao nhanh?
- [ ] A) Index cover toàn bộ bảng
- [ ] B) Index trên tất cả cột
- [x] C) Index chứa đủ cột mà query cần — database đọc từ index mà không cần truy cập table (Index-Only Scan)
- [ ] D) Index tự động tạo bởi database
💡 Giải thích: Query
SELECT name FROM users WHERE email = 'x'— nếu index trên (email, name), database lấy cả email (để filter) và name (để return) từ index, không cần đọc table row. Giảm I/O đáng kể.