Các loại Index trongPostgreSQL đóng vai trò rất quan trọng trong việc tối ưu hiệu năng truy vấn dữ liệu. Khi dữ liệu trong bảng ngày càng lớn, việc tìm kiếm thông tin bằng cách quét toàn bộ bảng sẽ trở nên chậm và tốn tài nguyên. Index giúp database tạo ra một “lối tắt” để xác định vị trí dữ liệu cần tìm, từ đó giảm đáng kể thời gian truy vấn.
PostgreSQL hỗ trợ nhiều loại index khác nhau, mỗi loại được thiết kế để phù hợp với từng kiểu dữ liệu và mục đích truy vấn riêng. Việc hiểu rõ các loại index sẽ giúp lập trình viên, DBA và Data Engineer thiết kế cơ sở dữ liệu hiệu quả hơn và cải thiện hiệu năng hệ thống.

Index trong PostgreSQL là gì
Index (chỉ mục) là một cấu trúc dữ liệu đặc biệt giúp tăng tốc độ truy vấn dữ liệu. Nó hoạt động tương tự như mục lục của một cuốn sách: thay vì đọc toàn bộ nội dung, bạn chỉ cần tra mục lục để tìm đúng trang cần đọc.
Khi một cột được tạo index, PostgreSQL sẽ xây dựng một cấu trúc dữ liệu riêng chứa: giá trị của cột và con trỏ đến vị trí dữ liệu trong bảng
Nhờ đó, database có thể nhanh chóng xác định vị trí của dữ liệu cần tìm mà không cần quét toàn bộ bảng.
Ví dụ một truy vấn:
SELECT * FROM customers
WHERE first_name = 'Hoàng';
Nếu không có index, PostgreSQL phải Sequential Scan (quét tuần tự toàn bảng) như sau:
row1 → kiểm tra điều kiện
row2 → kiểm tra điều kiện
row3 → kiểm tra điều kiện …
Khi bảng có hàng triệu dòng, quá trình này sẽ rất chậm. Index giúp PostgreSQL tìm nhanh những dòng cần thiết.
Vì sao Index giúp tăng tốc truy vấn? Index giúp tối ưu truy vấn vì:
- Giảm số lượng dòng cần đọc
- Tránh quét toàn bộ bảng
- Tăng tốc các điều kiện lọc trong WHERE
- Hỗ trợ JOIN, ORDER BY, GROUP BY
Tuy nhiên, index không phải lúc nào cũng tốt. Mỗi index là một cấu trúc dữ liệu riêng, nên khi dữ liệu thay đổi, PostgreSQL phải cập nhật thêm index tương ứng. Điều này làm cho các thao tác ghi dữ liệu như INSERT, UPDATE, DELETE chậm hơn. Do đó, việc thiết kế index cần cân bằng giữa tốc độ đọc và chi phí cập nhật dữ liệu.
Các loại Index trong PostgreSQL
PostgreSQL hỗ trợ nhiều loại index khác nhau, mỗi loại phù hợp với từng kiểu truy vấn.
B-Tree Index (mặc định)
B-Tree là loại index phổ biến nhất và cũng là loại index mặc định trong PostgreSQL. Nó phù hợp với hầu hết các truy vấn thông thường. B-Tree hỗ trợ các toán tử: = , > , <, >= , <=, BETWEEN, IN, IS NULL
Cú pháp tạo B-Tree index như sau:
CREATE INDEX ten_index
ON ten_bang(ten_cot);
Ví dụ: Tạo index cho cột first_name:
CREATE INDEX idx_customers_first_name
ON customers(first_name);
Sau khi tạo index xong, trong pgAdmin4 có thể xem bằng cách mở bảng (bên cột trái) , vào mục Indexes và xem Properties của index mới tạo.

Khi đã có index, PostgreSQL có thể sử dụng Index Scan hoặc Bitmap Scan thay vì quét toàn bộ bảng như Seq Scan toàn bộ bản.
Hash Index
Hash index được thiết kế để tối ưu các phép so sánh bằng (=). Nó sử dụng hàm hash để ánh xạ giá trị sang vị trí lưu trữ trong index. Cú pháp tạo index như sau:
CREATE INDEX ten_index
ON ten_bang USING HASH(ten_cot);
Ví dụ: Tạo hash index cho cột phone:
CREATE INDEX idx_customers_phone_hash
ON customers USING HASH(phone);
Hash index thường được dùng khi truy vấn chủ yếu là so sánh bằng. Tuy nhiên, trong nhiều trường hợp B-Tree vẫn là lựa chọn phổ biến hơn vì hỗ trợ nhiều loại truy vấn linh hoạt hơn.
Sau khi tạo index xong, trong pgAdmin4 có thể xem bằng cách mở bảng (bên cột trái) , vào mục Indexes và xem Properties của index mới tạo.

GIN (Generalized Inverted Index)
Loại index này được thiết kế để index các cấu trúc dữ liệu phức tạp như: Full-text search, JSONB, Array. GIN hoạt động bằng cách lưu danh sách các vị trí xuất hiện của từng giá trị, giúp tìm kiếm trong dữ liệu lớn nhanh hơn. Cú pháp tạo index như sau:
CREATE INDEX ten_index
ON ten_bang USING GIN(ten_cot);
Ví dụ Tạo index cho tìm kiếm văn bản:
CREATE INDEX idx_products_description_gin
ON products USING GIN(to_tsvector('simple', description));
Tạo index xong, Bạn có thể xem Index trong pgAdmin4 bằng cách mở bảng (bên cột trái) , vào mục Indexes và xem Properties của index mới tạo.

GIN index thường được sử dụng trong các hệ thống cần tìm kiếm nội dung văn bản hoặc dữ liệu JSON.
GiST (Generalized Search Tree) Index
GiST index là một cấu trúc index linh hoạt có thể hỗ trợ nhiều loại dữ liệu khác nhau như: dữ liệu hình học (geometric data) , dữ liệu không gian (spatial data), range types, full-text search. Cú pháp tạo index như sau:
CREATE INDEX ten_index
ON ten_bang USING GIST(ten_cot);
Ví dụ tạo index:
CREATE INDEX idx_products_name_gist
ON products USING GIST(to_tsvector('simple', product_name));
Tạo index xong, có thể xem Index trong pgAdmin4 bằng cách mở bảng (bên cột trái) , vào mục Indexes và xem Properties của index mới tạo.

So với GIN:
| Tiêu chí | GIN | GiST |
| Tốc độ tìm kiếm | rất nhanh | chậm hơn |
| Kích thước index | lớn | nhỏ hơn |
| Insert / Update | chậm | nhanh hơn |
| Full-text search | tốt nhất | dùng được |
Partial Index
Partial index là index chỉ áp dụng cho một phần dữ liệu thỏa điều kiện nhất định. Điều này giúp tiết kiệm dung lượng lưu trữ và cải thiện hiệu năng truy vấn trong những trường hợp cụ thể. Cú pháp tạo index như sau:
CREATE INDEX ten_index
ON ten_bang(ten_cot)
WHERE dieu_kien;
Ví dụ Tạo index cho các đơn hàng đã giao:
CREATE INDEX idx_orders_delivered
ON orders(order_date)
WHERE status = 'Delivered';
Index này chỉ lưu các dòng có status = ‘Delivered’, do đó nhỏ hơn và hiệu quả hơn so với index trên toàn bộ bảng.
Ảnh hưởng của Index đến INSERT, UPDATE, DELETE
Index giúp tăng tốc truy vấn SELECT, nhưng lại làm chậm các thao tác ghi dữ liệu.
Ảnh hưởng đến INSERT
Khi thêm một dòng mới vào bảng, PostgreSQL phải:
- Ghi dữ liệu vào bảng
- Chèn entry tương ứng vào từng index
Nếu bảng có nhiều index, mỗi lần INSERT sẽ phải cập nhật nhiều cấu trúc dữ liệu khác nhau, dẫn đến tăng chi phí I/O và CPU.
Ảnh hưởng đến UPDATE
Nếu cập nhật một cột có index, PostgreSQL phải:
- xóa entry cũ trong index
- thêm entry mới với giá trị cập nhật
Điều này làm chi phí cập nhật tăng lên.
Ảnh hưởng đến DELETE
Khi xóa dữ liệu, PostgreSQL phải:
- đánh dấu dòng trong bảng
- xóa hoặc cập nhật entry tương ứng trong tất cả các index
Do đó, càng nhiều index thì chi phí xóa dữ liệu càng lớn.
Khi nào nên tạo Index
Index nên được tạo khi:
- Cột thường xuyên xuất hiện trong WHERE
- Cột dùng để JOIN
- Cột dùng trong ORDER BY
- Bảng có số lượng dữ liệu lớn
Không nên tạo quá nhiều index khi:
- bảng thường xuyên INSERT/UPDATE
- dữ liệu thay đổi liên tục
- index ít khi được sử dụng
Xóa Index
Khi index không còn cần thiết, có thể xóa bằng lệnh:
DROP INDEX IF EXISTS ten_index;
Ví dụ:
DROP INDEX IF EXISTS idx_customers_email;
Kết luận
Các loại Index trong PostgreSQL là một công cụ quan trọng giúp tăng tốc độ truy vấn dữ liệu và cải thiện hiệu năng của hệ thống database. PostgreSQL cung cấp nhiều loại index khác nhau như B-Tree, Hash, GIN, GiST và Partial Index, mỗi loại phù hợp với những tình huống truy vấn cụ thể.
Việc hiểu rõ các loại Index trong PostgreSQL giúp lập trình viên và quản trị cơ sở dữ liệu thiết kế hệ thống hiệu quả hơn, tối ưu truy vấn và đảm bảo cân bằng giữa tốc độ đọc dữ liệu và chi phí cập nhật dữ liệu.


