Điều đầu tiên bạn phải biết là các 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ỉ số 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 + Tree, lưu trữ các phần tử theo thứ tự được sắp xếp. Ngoài ra, bạn không phải truy cập vào bảng thực để lấy các giá trị được lập chỉ mục, điều này làm cho cách truy vấn của bạn 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ự bạn truy vấn các trường này rất quan trọng .
Vì vậy, đưa ra 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 lợi thế của chỉ mục:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
Nhưng người sau sẽ không
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
Bởi vì bạn đang truy vấn first_name
cột trước 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ồi 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ỉ số băm
Đây là một loại chỉ mục khác mà thật không may, chỉ hỗ trợ bộ nhớ phụ trợ. Nó nhanh như chớp nhưng chỉ hữu ích cho việc tra cứu đầy đủ, điều đó 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 cuối bộ nhớ, nên có lẽ bạn sẽ không sử dụng nó thường xuyên. Trường hợp chính tôi có thể nghĩ ra 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 rất nhiều lựa chọn khác trong bảng tạm thời này bằng cách sử dụng các chỉ mục băm.
Nếu bạn có một VARCHAR
trường 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 hàm băm của giá trị 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 gọi url_hash
và sử dụng 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 một cái gì đó như thế này:
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ẽ kết thúc với rất nhiều xung đột 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 thực hiện như sau:
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
Vẫn có giá trị để băm mọi thứ ngay cả khi số lần va chạm cao vì bạn sẽ chỉ thực hiện so sánh thứ hai (chuỗi một) so với các giá trị băm lặp đi 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 phải nhấn bảng để so sánh url
trường.
Gói (lại
Một số sự thật mà bạn có thể xem xét mỗi khi bạn muốn nói về tối ưu hóa:
So sánh số nguyên là cách 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ỉ số 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, không chậm hơn. Nó có thể được minh họa bằng việc bạn có thể tối ưu hóa SELECT
bằng cách chia nó thành hai bước, tạo giá trị lưu trữ đầu tiên trong bảng trong bộ nhớ mới được tạo, sau đó 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 one được sử dụng nhiều nhất từ trước đến nay và hàm băm là một điều tốt để biết, nhưng bạn có thể tìm thấy các chỉ mục khác trong tài liệu MySQL .
Tôi đặc biệt 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ề các chỉ mục.