Điều đầu tiên bạn phải biết là chỉ mục là một cách để tránh quét toàn bộ bảng để có được kết quả mà bạn đang tìm kiếm.
Có nhiều loại chỉ mục khác nhau và chúng được triển khai trong lớp lưu trữ, vì vậy không có tiêu chuẩn nào giữa chúng và chúng cũng phụ thuộc vào công cụ lưu trữ mà bạn đang sử dụng.
InnoDB và chỉ mục B + Tree
Đối với InnoDB, loại chỉ mục phổ biến nhất là chỉ mục dựa trên B + Cây, lưu trữ các phần tử theo thứ tự đã được sắp xếp. Ngoài ra, bạn không cần phải truy cập vào bảng thực để nhận các giá trị được lập chỉ mục, điều này làm cho truy vấn của bạn quay trở lại nhanh hơn.
"Vấn đề" về loại chỉ mục này là bạn phải truy vấn giá trị ngoài cùng bên trái để sử dụng chỉ mục. Vì vậy, nếu chỉ mục của bạn có hai cột, giả sử last_name và first_name, thứ tự mà bạn truy vấn các trường này rất quan trọng .
Vì vậy, cho bảng sau:
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
Truy vấn này sẽ tận dụng chỉ mục:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
Nhưng cái sau sẽ không
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
Vì bạn đang truy vấn first_name
đầu tiên và nó không phải là cột ngoài cùng bên trái trong chỉ mục.
Ví dụ cuối cùng này thậm chí còn tệ hơn:
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
Bởi vì bây giờ, bạn đang so sánh phần ngoài cùng bên phải của trường ngoài cùng bên phải trong chỉ mục.
Chỉ mục băm
Đây là một kiểu chỉ mục khác mà không may là chỉ có phần phụ trợ bộ nhớ mới hỗ trợ. Nó nhanh như chớp nhưng chỉ hữu ích khi tra cứu đầy đủ, có nghĩa là bạn không thể sử dụng nó cho các hoạt động như >
, <
hoặc LIKE
.
Vì nó chỉ hoạt động cho phần phụ trợ bộ nhớ, bạn có thể sẽ không sử dụng nó thường xuyên. Trường hợp chính mà tôi có thể nghĩ đến ngay bây giờ là trường hợp bạn tạo một bảng tạm thời trong bộ nhớ với một tập hợp kết quả từ một lựa chọn khác và thực hiện nhiều lựa chọn khác trong bảng tạm thời này bằng cách sử dụng chỉ mục băm.
Nếu bạn có VARCHAR
lớn , bạn có thể "mô phỏng" việc sử dụng chỉ mục băm khi sử dụng B-Tree, bằng cách tạo một cột khác và lưu một giá trị băm lớn trên đó. Giả sử bạn đang lưu trữ một url trong một trường và các giá trị khá lớn. Bạn cũng có thể tạo một trường số nguyên có tên là url_hash
và sử dụng một hàm băm như CRC32
hoặc bất kỳ hàm băm nào khác để băm url khi chèn nó. Và sau đó, khi bạn cần truy vấn giá trị này, bạn có thể làm như sau:
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
Vấn đề với ví dụ trên là do CRC32
hàm tạo ra một hàm băm khá nhỏ, bạn sẽ gặp rất nhiều va chạm trong các giá trị được băm. Nếu bạn cần các giá trị chính xác, bạn có thể khắc phục sự cố này bằng cách làm như sau:
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
Vẫn đáng để băm mọi thứ ngay cả khi số lượng xung đột cao vì bạn sẽ chỉ thực hiện phép so sánh thứ hai (chuỗi một) so với các lần băm lặp lại.
Thật không may, bằng cách sử dụng kỹ thuật này, bạn vẫn cần nhấn vào bảng để so sánh url
trường.
Kết thúc
Một số sự kiện mà bạn có thể cân nhắc mỗi khi muốn nói về tối ưu hóa:
-
So sánh số nguyên nhanh hơn so với so sánh chuỗi. Nó có thể được minh họa bằng ví dụ về mô phỏng chỉ mục băm trong
InnoDB
. -
Có thể, thêm các bước bổ sung trong một quy trình làm cho nó nhanh hơn chứ không phải chậm hơn. Nó có thể được minh họa bằng thực tế rằng bạn có thể tối ưu hóa một
SELECT
bằng cách chia nó thành hai bước, làm cho bước đầu tiên lưu trữ các giá trị trong bảng trong bộ nhớ mới được tạo, rồi thực hiện các truy vấn nặng hơn trên bảng thứ hai này.
MySQL cũng có các chỉ mục khác, nhưng tôi nghĩ B + Tree là loại được sử dụng nhiều nhất từ trước đến nay và hash là một điều tốt cần biết, nhưng bạn có thể tìm các chỉ mục khác trong Tài liệu về MySQL .
Tôi thực sự khuyên bạn nên đọc cuốn sách "MySQL Hiệu suất Cao", câu trả lời ở trên chắc chắn dựa trên chương của nó về chỉ mục.