Database Indexes là gì?

Trong Backend, database không chỉ cần lưu trữ dữ liệu mà còn phải tìm kiếm và truy xuất dữ liệu hiệu quả. Khi số lượng bản ghi tăng lên, những truy vấn đơn giản như tìm một người dùng theo email hoặc tìm sản phẩm theo tên cũng có thể mất nhiều thời gian nếu database phải kiểm tra quá nhiều bản ghi.
Để cải thiện hiệu năng truy vấn, các hệ quản trị cơ sở dữ liệu như PostgreSQL và MySQL cung cấp cơ chế Index (chỉ mục).
Index giúp database tìm kiếm dữ liệu nhanh hơn trong nhiều trường hợp bằng cách xây dựng một cấu trúc dữ liệu hỗ trợ truy xuất, thay vì phải kiểm tra lần lượt toàn bộ bản ghi trong bảng.
1. Index là gì?
Database Index (chỉ mục cơ sở dữ liệu) là một cấu trúc dữ liệu được xây dựng dựa trên một hoặc nhiều cột của bảng, nhằm hỗ trợ database tìm kiếm, sắp xếp hoặc truy xuất dữ liệu hiệu quả hơn.
Có thể hình dung index giống như mục lục của một cuốn sách. Nếu muốn tìm một chủ đề trong cuốn sách dày hàng nghìn trang, bạn có thể tra mục lục để xác định vị trí thay vì đọc lần lượt từ trang đầu tiên.
Tương tự, khi tìm một sản phẩm theo ID, database có thể sử dụng index phù hợp để xác định vị trí bản ghi cần truy xuất.
Tuy nhiên, index không phải là bản sao đầy đủ của bảng. Nó là một cấu trúc dữ liệu bổ sung, lưu các giá trị được lập chỉ mục cùng thông tin cần thiết để tìm đến dữ liệu tương ứng.
2. Database truy vấn dữ liệu như thế nào khi không có Index?
Giả sử hệ thống có bảng users chứa một triệu người dùng và cần tìm người dùng theo email:
SELECT *
FROM users
WHERE email = '[email protected]';
Nếu không có index phù hợp và database lựa chọn phương pháp quét toàn bộ bảng (Sequential Scan hoặc Table Scan), nó có thể phải kiểm tra một lượng lớn bản ghi để tìm kết quả phù hợp.
Cách truy vấn này có thể chấp nhận được với bảng nhỏ, nhưng khi dữ liệu tăng lên, chi phí đọc và kiểm tra dữ liệu có thể trở nên đáng kể.
Khi có index trên cột email, database có thể sử dụng cấu trúc chỉ mục để tìm vị trí dữ liệu nhanh hơn mà không cần quét toàn bộ bảng trong nhiều trường hợp.
Lưu ý rằng database có thể tự quyết định sử dụng index hay quét bảng dựa trên kế hoạch thực thi, số lượng dữ liệu, độ chọn lọc của điều kiện và chi phí ước tính. Có index không đồng nghĩa mọi truy vấn đều tự động nhanh hơn.
3. Tạo Index trong PostgreSQL
Ví dụ, tạo bảng users:
CREATE TABLE users (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Để tìm kiếm người dùng theo email hiệu quả hơn, có thể tạo index:
CREATE INDEX idx_users_email
ON users(email);
Sau đó, truy vấn:
SELECT *
FROM users
WHERE email = '[email protected]';
có thể sử dụng index idx_users_email nếu PostgreSQL xác định đó là phương án thực thi phù hợp.
Trong ví dụ trên:
CREATE INDEXlà câu lệnh tạo chỉ mục.idx_users_emaillà tên index.users(email)cho biết index được xây dựng trên cộtemailcủa bảngusers.
Vì email thường được sử dụng để tìm người dùng và có thể cần bảo đảm không trùng lặp, hệ thống thực tế có thể cân nhắc dùng UNIQUE hoặc ràng buộc UNIQUE thay vì chỉ tạo index thông thường.
Ví dụ:
CREATE UNIQUE INDEX idx_users_email_unique
ON users(email);
Index duy nhất giúp ngăn các giá trị email trùng nhau theo quy tắc so sánh của database. Tuy nhiên, cách xử lý giá trị NULL và tính duy nhất còn phụ thuộc vào hệ quản trị cơ sở dữ liệu và cấu hình cụ thể.
4. Các loại Index phổ biến
Các hệ quản trị cơ sở dữ liệu hỗ trợ nhiều loại index, mỗi loại phù hợp với những kiểu dữ liệu và truy vấn khác nhau.
4.1. B-tree Index
B-tree là loại index phổ biến, đặc biệt phù hợp với các phép so sánh bằng, so sánh khoảng và nhiều truy vấn sắp xếp.
Ví dụ:
CREATE INDEX idx_products_price
ON products(price);
Index này có thể hỗ trợ những truy vấn như:
SELECT *
FROM products
WHERE price >= 100000
AND price <= 500000;
B-tree phù hợp với nhiều trường hợp truy vấn thông thường trên các cột như ID, email, giá sản phẩm hoặc thời gian tạo bản ghi.
4.2. Composite Index
Composite Index (chỉ mục kết hợp) là index được xây dựng trên nhiều cột.
Ví dụ:
CREATE INDEX idx_orders_customer_created
ON orders(customer_id, created_at);
Index này có thể hữu ích cho truy vấn:
SELECT *
FROM orders
WHERE customer_id = 10
ORDER BY created_at DESC;
Thứ tự các cột trong composite index rất quan trọng. Index (customer_id, created_at) thường hữu ích cho điều kiện lọc theo customer_id, nhưng không nhất thiết hiệu quả tương đương khi chỉ lọc theo created_at.
Vì vậy, khi thiết kế composite index, cần xem xét các truy vấn thực tế mà hệ thống thường thực hiện.
4.3. Unique Index
Unique Index bảo đảm các giá trị được lập chỉ mục không vi phạm quy tắc duy nhất.
Ví dụ:
CREATE UNIQUE INDEX idx_users_email
ON users(email);
Loại index này thường được sử dụng khi một cột hoặc tổ hợp cột cần có giá trị duy nhất, chẳng hạn email tài khoản.
4.4. Một số loại Index khác
Ngoài các loại trên, PostgreSQL còn hỗ trợ những loại index như:
- Hash: phù hợp với phép so sánh bằng trong những trường hợp được hỗ trợ.
- GIN: thường dùng cho dữ liệu như mảng, JSONB hoặc tìm kiếm toàn văn bản.
- GiST: hỗ trợ các kiểu truy vấn và cấu trúc dữ liệu như dữ liệu không gian.
- BRIN: có thể hiệu quả với bảng rất lớn mà giá trị trong các cột có tương quan với thứ tự lưu trữ vật lý, chẳng hạn dữ liệu thời gian được ghi tuần tự.
Không cần ghi nhớ mọi loại index ngay từ đầu. Với Backend cơ bản, nên hiểu B-tree, composite index và unique index trước, sau đó tìm hiểu các loại khác khi gặp nhu cầu thực tế.
5. Index có nhược điểm gì?
Index không chỉ mang lại lợi ích về hiệu năng mà còn phát sinh chi phí.
Tốn thêm dung lượng lưu trữ
Database phải lưu thêm cấu trúc index bên cạnh dữ liệu gốc. Bảng có nhiều index có thể tiêu tốn thêm đáng kể dung lượng.
Làm chậm một số thao tác ghi
Khi thực hiện INSERT, UPDATE hoặc DELETE, database có thể phải cập nhật các index liên quan. Vì vậy, quá nhiều index có thể làm tăng chi phí ghi dữ liệu.
Không phải truy vấn nào cũng cần Index
Nếu bảng nhỏ hoặc truy vấn cần lấy phần lớn dữ liệu trong bảng, quét toàn bộ bảng đôi khi có thể rẻ hơn việc sử dụng index rồi truy xuất thêm nhiều bản ghi.
Index cũng có thể không hữu ích nếu điều kiện truy vấn không phù hợp với cấu trúc chỉ mục hoặc cột được lập chỉ mục có độ chọn lọc thấp trong trường hợp cụ thể.
Do đó, việc tạo index nên dựa trên truy vấn thực tế và kết quả đo lường, thay vì tạo index cho mọi cột.
6. Kiểm tra hiệu năng truy vấn bằng EXPLAIN
Trong PostgreSQL, có thể sử dụng EXPLAIN để xem kế hoạch thực thi mà database dự định sử dụng:
EXPLAIN
SELECT *
FROM users
WHERE email = '[email protected]';
Để đo thời gian thực thi và xem thêm các thông tin thực tế về quá trình xử lý, có thể dùng:
EXPLAIN ANALYZE
SELECT *
FROM users
WHERE email = '[email protected]';
EXPLAIN ANALYZE thực sự chạy câu truy vấn. Vì vậy, cần thận trọng khi sử dụng với các câu lệnh thay đổi dữ liệu.
Khi đọc kết quả, có thể bắt đầu bằng việc nhận diện:
Seq Scan: quét tuần tự bảng.Index Scan: truy xuất bản ghi thông qua index.Bitmap Index ScanvàBitmap Heap Scan: các bước thường được PostgreSQL kết hợp để tìm và đọc nhiều bản ghi phù hợp.
Không nên mặc định rằng Index Scan luôn tốt hơn Seq Scan. Điều quan trọng là kế hoạch thực thi có phù hợp với lượng dữ liệu và mục tiêu của truy vấn hay không.
7. Vì sao Backend Developer cần hiểu Database Indexes?
Khi xây dựng API, lập trình viên thường viết các truy vấn để tìm người dùng, lọc sản phẩm, lấy đơn hàng theo khách hàng hoặc sắp xếp dữ liệu theo thời gian.
Nếu không hiểu index, một API có thể hoạt động tốt với vài trăm bản ghi nhưng trở nên chậm khi dữ liệu tăng lên.
Ngược lại, việc thiết kế index phù hợp có thể cải thiện đáng kể hiệu năng truy vấn. Tuy nhiên, lập trình viên vẫn cần xem xét các yếu tố khác như cách viết SQL, số lượng dữ liệu trả về, thiết kế bảng, cache và kế hoạch thực thi.
8. Kết luận
Database Indexes là một chủ đề quan trọng trong quá trình phát triển Backend vì nó giúp hiểu cách database tìm kiếm và truy xuất dữ liệu hiệu quả.
Index có thể giảm lượng dữ liệu cần kiểm tra trong nhiều truy vấn, nhưng cũng tiêu tốn dung lượng và làm tăng chi phí cập nhật dữ liệu. Vì vậy, lập trình viên cần lựa chọn index dựa trên nhu cầu truy vấn thực tế và kết quả đo lường.








Khoá học lập trình game con rắn cho trẻ em




