Có index rồi mà truy vấn vẫn quét toàn bảng? Sargability và một hàm bọc quanh cột
Index là một cấu trúc sắp xếp theo giá trị của cột. Khi bạn bọc một hàm quanh cột — date_part('year', tao_luc), LOWER(email), CAST(...) — thì thứ bạn đang so sánh không còn là giá trị đã được sắp xếp nữa, nên database không dùng index được và phải quét toàn bảng. Điều kiện dùng được index gọi là sargable. Đo trên PostgreSQL 16 với 200.000 dòng: bản bọc hàm chạy 29,6 ms với Seq Scan, bản viết lại thành khoảng chạy 5,4 ms với Bitmap Index Scan — nhanh hơn ~5,4 lần và trả về cùng 37.518 dòng.
Tình huống quen thuộc: truy vấn chậm, bạn tạo index lên đúng cột đang lọc, chạy lại — vẫn chậm y như cũ. Index nằm đó, \d thấy rõ, nhưng execution plan không hề nhắc tới nó.
Bài này đào sâu bài Index và bài tối ưu truy vấn trong series học SQL 30 ngày. Mọi con số là kết quả chạy thật trên PostgreSQL 16.11.