PostgreSQL - Chỉ mục: Hướng dẫn cho người mới bắt đầu

Xin chào các bạn future database wizards! Hôm nay, chúng ta sẽ bắt đầu một chuyến hành trình thú vị vào thế giới của các chỉ mục PostgreSQL. Đừng lo lắng nếu bạn chưa bao giờ viết một dòng mã trước đây - tôi sẽ là người hướng dẫn thân thiện của bạn, và chúng ta sẽ cùng khám phá chủ đề này từng bước một. Vậy, hãy lấy một ly đồ uống yêu thích của bạn, và cùng tôi bắt đầu nhé!

PostgreSQL - Indexes

什么是索引?

Trước khi chúng ta đi vào chi tiết, hãy bắt đầu với một ví dụ đơn giản. Hãy tưởng tượng bạn đang ở trong một thư viện và tìm kiếm một cuốn sách cụ thể. Nếu không có hệ thống tổ chức nào, bạn sẽ phải tìm kiếm qua từng cuốn sách để tìm ra cuốn bạn muốn. Điều đó sẽ mất rất nhiều thời gian! Nhưng may mắn thay, các thư viện có chỉ mục - như các catalo thẻ hoặc hệ thống máy tính - giúp bạn nhanh chóng tìm thấy cuốn sách bạn cần.

Trong thế giới dữ liệu, các chỉ mục có mục đích tương tự. Chúng là các bảng tra cứu đặc biệt mà engine tìm kiếm của cơ sở dữ liệu có thể sử dụng để tăng tốc độ truy xuất dữ liệu. Nói chung, một chỉ mục là một cấu trúc dữ liệu cải thiện tốc độ các thao tác trong một bảng.

Hãy tạo một bảng đơn giản để làm việc trong suốt hướng dẫn này:

CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
age INT,
grade CHAR(1)
);

INSERT INTO students (name, age, grade) VALUES
('Alice', 18, 'A'),
('Bob', 19, 'B'),
('Charlie', 20, 'A'),
('David', 18, 'C'),
('Eve', 19, 'B');

Điều này tạo ra một bảng叫做 students với bốn cột: id, name, age, và grade. Chúng ta cũng đã thêm một số dữ liệu mẫu để làm việc.

Loại chỉ mục

Bây giờ chúng ta đã có bảng, hãy cùng khám phá các loại chỉ mục mà PostgreSQL cung cấp. Mỗi loại có những ưu thế riêng và phù hợp cho các tình huống khác nhau.

1. Chỉ mục B-tree

B-tree (Balanced tree) là loại chỉ mục mặc định trong PostgreSQL. Nó giống như một cây kéo đa năng - linh hoạt và tốt cho hầu hết các tình huống.

Hãy tạo một chỉ mục B-tree trên cột name:

CREATE INDEX idx_student_name ON students USING BTREE (name);

Chỉ mục này sẽ đặc biệt hữu ích cho các truy vấn tìm kiếm hoặc sắp xếp theo cột name.

2. Chỉ mục Hash

Chỉ mục Hash được tối ưu hóa cho các so sánh bằng. Chúng giống như một từ điển nơi bạn có thể nhanh chóng tra cứu một từ.

Hãy tạo một chỉ mục Hash trên cột age:

CREATE INDEX idx_student_age ON students USING HASH (age);

Chỉ mục này sẽ tăng tốc các truy vấn tìm kiếm các giá trị age chính xác, như WHERE age = 18.

3. Chỉ mục GiST

Chỉ mục GiST (Generalized Search Tree) hữu ích cho tìm kiếm văn bản toàn cục và cho việc chỉ mục dữ liệu hình học hoặc các loại dữ liệu tùy chỉnh.

Dưới đây là một ví dụ về tạo chỉ mục GiST cho tìm kiếm văn bản toàn cục:

CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX idx_student_name_gist ON students USING GIST (name gist_trgm_ops);

Chỉ mục này sẽ hữu ích cho các so sánh phần tử hoặc tìm kiếm tương tự trên cột name.

4. Chỉ mục GIN

Chỉ mục GIN (Generalized Inverted Index) tốt nhất cho các cột chứa nhiều giá trị trong một cột duy nhất, như các mảng hoặc dữ liệu JSON.

Hãy thêm một cột JSON vào bảng của chúng ta và tạo một chỉ mục GIN:

ALTER TABLE students ADD COLUMN hobbies JSONB;
CREATE INDEX idx_student_hobbies ON students USING GIN (hobbies);

Chỉ mục này sẽ hữu ích cho việc truy vấn các sở thích cụ thể trong dữ liệu JSON.

Dưới đây là bảng tóm tắt các loại chỉ mục này:

Loại chỉ mục Tốt nhất cho Ví dụ sử dụng
B-tree Mục đích tổng quát, sắp xếp Tìm kiếm hoặc sắp xếp theo tên
Hash So sánh bằng Tìm kiếm các giá trị age chính xác
GiST Tìm kiếm văn bản toàn cục, dữ liệu hình học So sánh phần tử tên
GIN Dữ liệu mảng hoặc JSON Tìm kiếm trong các trường JSON

Chỉ mục từng phần

Đôi khi, bạn chỉ cần chỉ mục một phần dữ liệu. Đó là lúc chỉ mục từng phần phát huy tác dụng. Chúng giống như tạo một chỉ mục cho một phần cụ thể của một cuốn sách.

Hãy tạo một chỉ mục từng phần cho học sinh có điểm 'A':

CREATE INDEX idx_student_grade_a ON students (name) WHERE grade = 'A';

Chỉ mục này sẽ tăng tốc các truy vấn cụ thể tìm kiếm học sinh có điểm 'A'.

Chỉ mục tự động

PostgreSQL tự động tạo chỉ mục trong một số trường hợp. Thường gặp nhất là khi bạn xác định một PRIMARY KEY hoặc một ràng buộc UNIQUE.

Trong bảng students, PostgreSQL tự động tạo một chỉ mục trên cột id vì chúng ta đã xác định nó là PRIMARY KEY.

Lệnh DROP INDEX

Chúng ta có thể tạo chỉ mục, và cũng có thể xóa chúng khi chúng không còn cần thiết. Dưới đây là cách bạn có thể xóa một chỉ mục:

DROP INDEX idx_student_name;

Hãy cẩn thận với lệnh này - việc xóa một chỉ mục có thể ảnh hưởng lớn đến hiệu suất truy vấn nếu chỉ mục đó đang được sử dụng.

Khi nào nên tránh sử dụng chỉ mục?

Mặc dù chỉ mục có thể cải thiện hiệu suất truy vấn, nhưng chúng không phải lúc nào cũng là giải pháp tốt nhất. Dưới đây là một số tình huống bạn có thể muốn suy nghĩ twice trước khi tạo một chỉ mục:

  1. Bảng nhỏ: Nếu một bảng có rất ít hàng, một cuộc quét toàn bảng có thể nhanh hơn việc sử dụng chỉ mục.

  2. Bảng thường xuyên được cập nhật: Chỉ mục cần được cập nhật khi dữ liệu bảng thay đổi, điều này có thể làm chậm các thao tác ghi.

  3. Cột có độ chọn thấp: Nếu một cột có rất ít giá trị duy nhất so với tổng số hàng, một chỉ mục có thể không rất hữu ích.

  4. Bảng hiếm khi được truy vấn: Nếu một bảng chủ yếu được sử dụng cho việc ghi dữ liệu và hiếm khi được truy vấn, chi phí bảo trì chỉ mục có thể vượt qua lợi ích.

Nhớ rằng, việc chỉ mục là một nghệ thuật cũng như một khoa học. Nó thường đòi hỏi thử nghiệm và kiểm tra hiệu suất để tìm ra sự cân bằng đúng đắn cho tình huống cụ thể của bạn.

Và thế là bạn đã có nó, các bạn! Chúng ta đã cùng nhau hành trình qua vùng đất của các chỉ mục PostgreSQL, từ cơ bản đến một số khái niệm nâng cao. Tôi hy vọng hướng dẫn này đã giúp bạn hiểu rõ hơn về chỉ mục. Nhớ rằng, thực hành là cách tốt nhất để hoàn thiện, vì vậy đừng ngần ngại thử nghiệm các khái niệm này trong các dự án cơ sở dữ liệu của riêng bạn.

Chúc các bạn thành công trong việc chỉ mục, và mong rằng các truy vấn của bạn luôn nhanh chóng!

Credits: Image by storyset