Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Bảng có vài chục nghìn dòng thì truy vấn nào cũng nhanh. Đến hàng triệu dòng, một câu WHERE thiếu chỉ mục có thể làm cả trang web chậm hẳn. Hiểu chỉ mục là kỹ năng database đáng giá nhất mà một lập trình viên backend có thể học sớm.
Hãy tưởng tượng một cuốn sách dày không có mục lục: tìm một từ phải lật từng trang. Chỉ mục giống mục lục của bảng: một cấu trúc dữ liệu riêng (thường là B-tree) giúp database nhảy thẳng tới các dòng phù hợp thay vì quét toàn bộ bảng (full table scan).
Đổi lại, chỉ mục chiếm dung lượng và làm thao tác ghi (INSERT, UPDATE, DELETE) chậm hơn một chút, vì phải cập nhật cả chỉ mục. Vì vậy không nên đánh chỉ mục cho mọi cột.
CREATE TABLE orders ( id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, user_id BIGINT UNSIGNED NOT NULL, status VARCHAR(20) NOT NULL, created_at DATETIME NOT NULL);CREATE INDEX idx_orders_user ON orders (user_id);CREATE INDEX idx_orders_user_created ON orders (user_id, created_at);CREATE UNIQUE INDEX uq_users_email ON users (email);Khóa chính tự động có chỉ mục. Chỉ mục duy nhất (UNIQUE) vừa tăng tốc tìm kiếm, vừa đảm bảo không có giá trị trùng.
EXPLAIN SELECT * FROM orders WHERE user_id = 42 ORDER BY created_at DESC LIMIT 20;Hãy chú ý vài cột trong kết quả:
type: ALL nghĩa là quét toàn bộ bảng (thường là điều cần tránh trên bảng lớn); ref, range, const là tốt hơn.key: chỉ mục thực sự được dùng.rows: số dòng ước tính database phải xem.Extra: Using filesort hay Using temporary là dấu hiệu cần cân nhắc.Chỉ mục trên nhiều cột (user_id, created_at) hoạt động theo thứ tự cột từ trái sang phải. Nó giúp cho truy vấn lọc theo user_id, hoặc theo cả user_id và created_at, nhưng không giúp được truy vấn chỉ lọc theo created_at. Đây gọi là quy tắc tiền tố trái (leftmost prefix).
Nguyên tắc chọn thứ tự cột: đặt cột dùng so sánh bằng (=) trước, rồi tới cột dùng để lọc khoảng hoặc sắp xếp. Với truy vấn ở trên, chỉ mục (user_id, created_at) vừa lọc theo người dùng vừa cho sẵn thứ tự theo thời gian, nên tránh được bước sắp xếp thêm.
WHERE YEAR(created_at) = 2024 vô hiệu hóa chỉ mục; hãy viết created_at >= '2024-01-01' AND created_at < '2025-01-01'.LIKE '%abc' không dùng được chỉ mục; LIKE 'abc%' thì được.Khi mọi cột mà truy vấn cần đều nằm trong chỉ mục, MySQL không cần đọc bản ghi gốc, gọi là covering index và rất nhanh. Vì vậy hạn chế dùng SELECT * khi chỉ cần vài cột, và đôi khi thêm cột vào chỉ mục để "bao phủ" những truy vấn nóng.
EXPLAIN để xem kế hoạch thực thi.Khóa ngoại giúp bảo toàn tính toàn vẹn dữ liệu, và InnoDB tự tạo chỉ mục trên cột khóa ngoại nếu chưa có. Dù vậy, hãy chủ động kiểm tra: các cột dùng trong JOIN và trong mệnh đề WHERE thường xuyên nên được đánh chỉ mục. Khi thiếu chỉ mục ở bảng được JOIN, một truy vấn nhìn có vẻ vô hại cũng có thể buộc MySQL quét nhiều lần cả bảng lớn. Sau mỗi lần thay đổi cấu trúc, hãy chạy lại EXPLAIN cho các truy vấn quan trọng để chắc chắn kế hoạch thực thi vẫn như mong đợi.
Chỉ mục không phải phép màu, nhưng khi dùng đúng chúng biến truy vấn từ vài giây xuống vài mili giây. Hãy tập thói quen: viết truy vấn, chạy EXPLAIN, và hỏi "chỉ mục nào phục vụ câu này?". Chỉ riêng thói quen đó đã giúp bạn tránh được phần lớn lỗi hiệu năng database.
Khi cần một lộ trình học có hệ thống, bạn có thể tham khảo khóa học trên codebem.com.
Nguyễn Đình Cường
0 comment