CodeGym /Các khóa học /SQL SELF /Làm sao chọn loại index phù hợp

Làm sao chọn loại index phù hợp

SQL SELF
Mức độ , Bài học
Có sẵn

Bọn mình đã đào sâu lý thuyết về index, làm quen với các loại index, học cách tạo và xóa, cũng như hiểu cách index các kiểu dữ liệu phức tạp như mảng và JSONB. Giờ là lúc nói về việc chọn đúng loại index để nó chạy hiệu quả cho bài toán của bạn — vì chọn sai là dễ toang lắm đó.

Hãy tưởng tượng database của bạn như một thư viện, còn các query là mấy bạn khách đi tìm sách. Nếu sách vứt lung tung dưới sàn, tìm kiếm sẽ thành một cuộc phiêu lưu bất tận. Index giống như mấy cái kệ và catalog được sắp xếp gọn gàng, giúp bạn tìm đúng thứ mình cần mà không phải lục tung mọi thứ lên.

Nhưng nếu bạn đặt nhầm kệ hoặc catalog, ví dụ dùng HASH-index chỗ lẽ ra phải dùng index cho tìm kiếm theo khoảng, thì giống như thủ thư chỉ có catalog theo năm xuất bản mà khách lại hỏi tên sách — tìm mệt nghỉ luôn, ai cũng kêu ca. Trong database thì nó thành query chậm rì và hệ thống bị đè nặng.

Hôm nay mình sẽ chỉ bạn cách chọn index chuẩn để query chạy vèo vèo mà database không bị đuối. Nếu chọn sai thì kết quả sẽ tệ lắm: query lag, tốn tài nguyên, thủ thư (PostgreSQL) ngồi buồn thiu.

Tiêu chí chọn index: checklist

Khi chọn index, tự hỏi mấy câu này nhé:

  1. Kiểu dữ liệu ở cột này là gì?
    • Ví dụ, số INTEGER, FLOAT thì thường dùng index B-TREE, mảng thì dùng GIN, còn trường text thì còn tùy bài toán.
  1. Bạn thường chạy query kiểu gì nhất?

    • WHERE field = value? Tìm kiếm chính xác? Có thể bạn sẽ cần B-TREE hoặc HASH.
    • Tìm kiếm theo mảng hoặc JSONB? Nghía qua GIN nhé.
    • Dữ liệu địa lý, khoảng giá trị? Nghĩ tới GiST đi.
  2. Dữ liệu của bạn thay đổi ra sao?

    • Nếu bảng có nhiều insert/update, đừng index quá nhiều, vì nó sẽ làm tăng overhead.
  3. Có cần đảm bảo uniqueness không?

    • Nếu có thì phải dùng index với thuộc tính UNIQUE.

Case thực tế: ví dụ chọn index

Cùng xem vài tình huống thực tế nhé.

1. Tìm kiếm chính xác

Bạn làm việc với database sinh viên và muốn tìm nhanh sinh viên theo email:

SELECT * FROM students WHERE email = 'student@example.com';

Điều quan trọng ở đây là tìm kiếm chính xác. Lựa chọn tốt nhất là index B-TREE, vì nó cực mạnh với tìm kiếm exact match.

CREATE INDEX idx_students_email ON students (email);

Hoặc nếu email phải unique:

CREATE UNIQUE INDEX idx_students_email_unique ON students (email);

2. Tìm kiếm theo khoảng

Giả sử bạn muốn tìm sinh viên trên 18 tuổi:

SELECT * FROM students WHERE age > 18;

Với tìm kiếm theo khoảng, B-TREE cũng rất ổn vì cấu trúc của nó sinh ra để tìm kiếm theo thứ tự.

CREATE INDEX idx_students_age ON students (age);

3. Lọc theo mảng

Bạn có bảng courses, trong đó một cột lưu mảng ID sinh viên đã đăng ký khóa học. Bạn muốn tìm tất cả các khóa mà sinh viên có ID 123 đã đăng ký.

SELECT * FROM courses WHERE student_ids @> ARRAY[123];

Với kiểu query này thì index GIN là chân ái, vì nó tối ưu cho mảng.

CREATE INDEX idx_courses_students_ids ON courses USING gin (student_ids);

4. Lấy dữ liệu từ JSONB

Giả sử bạn có bảng chứa dữ liệu JSONB, lưu thông tin đơn hàng. Bạn muốn tìm tất cả đơn hàng mà khách ở thành phố "Moscow":

SELECT * FROM orders WHERE data->>'city' = 'Moscow';

Ở đây dùng index GIN là hợp lý, vì nó giúp tìm kiếm theo key và value trong JSONB rất nhanh.

CREATE INDEX idx_orders_data ON orders USING gin (data);

5. Dữ liệu địa lý

Nếu bạn làm với dữ liệu địa lý, ví dụ muốn tìm tất cả điểm nằm trong bán kính nào đó, hãy dùng index GiST. Loại index này cực hợp với geometry và khoảng giá trị.

CREATE INDEX idx_locations_geom ON locations USING gist (geom);

So sánh hiệu năng các loại index

Lấy ví dụ thực tế tìm sinh viên theo email. Bảng có 1 triệu bản ghi. Thử chạy query với các loại index khác nhau và cả khi không có index:

Tình huống Thời gian thực thi
Không có index 1500 ms
Có index B-TREE 2 ms
Có index HASH 3 ms

Kết luận: trong trường hợp này, dùng index B-TREE tăng tốc query hơn 500 lần.

Lỗi thường gặp khi chọn index

Lỗi phổ biến nhất là tạo index "cho chắc ăn". Ví dụ, bạn index mọi cột trong bảng, rồi phát hiện insert bị chậm hẳn. Nhớ nhé, index không phải phép màu dùng lúc nào cũng được. Nó là công cụ mạnh nếu dùng đúng, nhưng dùng sai thì hại nhiều hơn lợi.

Lỗi khác là chọn sai loại index. Ví dụ, bạn dùng HASH index cho tìm kiếm theo khoảng, và query tự nhiên chậm như rùa. Đó là vì HASH index chỉ hợp cho tìm kiếm chính xác thôi.

Khuyến nghị khi chọn index

  • Nếu bạn hay tìm kiếm chính xác hoặc sắp xếp, dùng B-TREE.
  • Cho tìm kiếm chính xác mà muốn tiết kiệm RAM, có thể dùng HASH.
  • Làm việc với mảng hoặc JSONB thì chọn GIN.
  • Cho khoảng giá trị hoặc dữ liệu địa lý thì dùng GiST.

Và cuối cùng, lời khuyên quan trọng nhất: luôn phân tích query của bạn! Dùng lệnh EXPLAINEXPLAIN ANALYZE để xem PostgreSQL dùng index thế nào và có thể tối ưu gì thêm.

EXPLAIN ANALYZE
SELECT * FROM students WHERE email = 'student@example.com';

Vậy là xong cho hôm nay! Giờ bạn đã có kiến thức để chọn index như một Jedi chọn kiếm ánh sáng. Nhớ cẩn thận, đừng tạo index lung tung, và luôn kiểm tra xem nó ảnh hưởng hiệu năng ra sao nhé.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION