Không cho MySQL lập chỉ mục một giá trị đầy đủ của BLOB
, TEXT
và dài VARCHAR
cột vì dữ liệu chúng chứa có thể rất lớn, và mặc nhiên chỉ số DB sẽ lớn, có nghĩa là không có lợi ích từ chỉ mục.
MySQL yêu cầu bạn xác định N ký tự đầu tiên được lập chỉ mục và mẹo là chọn một số N đủ dài để có tính chọn lọc tốt, nhưng đủ ngắn để tiết kiệm không gian. Tiền tố phải đủ dài để làm cho chỉ mục gần như hữu ích nếu bạn lập chỉ mục cho toàn bộ cột.
Trước khi chúng ta đi xa hơn hãy để chúng tôi xác định một số điều khoản quan trọng. Độ chọn lọc chỉ mục là tỷ lệ của tổng giá trị được lập chỉ mục riêng biệt và tổng số hàng . Đây là một ví dụ cho bảng thử nghiệm:
+-----+-----------+
| id | value |
+-----+-----------+
| 1 | abc |
| 2 | abd |
| 3 | adg |
+-----+-----------+
Nếu chúng ta chỉ lập chỉ mục ký tự đầu tiên (N = 1), thì bảng chỉ mục sẽ trông giống như bảng sau:
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| a | 1,2,3 |
+---------------+-----------+
Trong trường hợp này, độ chọn lọc chỉ số bằng IS = 1/3 = 0,33.
Bây giờ chúng ta hãy xem điều gì sẽ xảy ra nếu chúng ta tăng số lượng ký tự được lập chỉ mục lên hai (N = 2).
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| ab | 1,2 |
| ad | 3 |
+---------------+-----------+
Trong kịch bản này IS = 2/3 = 0,66 có nghĩa là chúng tôi đã tăng độ chọn lọc chỉ mục, nhưng chúng tôi cũng đã tăng kích thước của chỉ mục. Thủ thuật là tìm số N tối thiểu sẽ dẫn đến độ chọn lọc chỉ số tối đa .
Có hai cách tiếp cận bạn có thể thực hiện tính toán cho bảng cơ sở dữ liệu của mình. Tôi sẽ thực hiện trình diễn trên bãi chứa cơ sở dữ liệu này .
Giả sử chúng tôi muốn thêm cột Last_name trong bảng nhân viên vào chỉ mục và chúng tôi muốn xác định số N nhỏ nhất sẽ tạo ra độ chọn lọc chỉ mục tốt nhất.
Đầu tiên chúng ta hãy xác định tên cuối cùng thường xuyên nhất:
select count(*) as cnt, last_name
from employees
group by employees.last_name
order by cnt
+-----+-------------+
| cnt | last_name |
+-----+-------------+
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Farris |
| 222 | Sudbeck |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Neiman |
| 218 | Mandell |
| 218 | Masada |
| 217 | Boudaillier |
| 217 | Wendorf |
| 216 | Pettis |
| 216 | Solares |
| 216 | Mahnke |
+-----+-------------+
15 rows in set (0.64 sec)
Như bạn có thể thấy, tên cuối cùng Baba là tên thường xuyên nhất. Bây giờ chúng ta sẽ tìm các tiền tố last_name xảy ra thường xuyên nhất , bắt đầu bằng các tiền tố năm chữ cái.
+-----+--------+
| cnt | prefix |
+-----+--------+
| 794 | Schaa |
| 758 | Mande |
| 711 | Schwa |
| 562 | Angel |
| 561 | Gecse |
| 555 | Delgr |
| 550 | Berna |
| 547 | Peter |
| 543 | Cappe |
| 539 | Stran |
| 534 | Canna |
| 485 | Georg |
| 417 | Neima |
| 398 | Petti |
| 398 | Duclo |
+-----+--------+
15 rows in set (0.55 sec)
Có nhiều lần xuất hiện hơn của mọi tiền tố, có nghĩa là chúng ta phải tăng số N cho đến khi các giá trị gần giống như trong ví dụ trước.
Đây là kết quả cho N = 9
select count(*) as cnt, left(last_name,9) as prefix
from employees
group by prefix
order by cnt desc
limit 0,15;
+-----+-----------+
| cnt | prefix |
+-----+-----------+
| 336 | Schwartzb |
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Sudbeck |
| 222 | Farris |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Mandell |
| 218 | Neiman |
| 218 | Masada |
| 217 | Wendorf |
| 217 | Boudailli |
| 216 | Cummings |
| 216 | Pettis |
+-----+-----------+
Đây là kết quả cho N = 10.
+-----+------------+
| cnt | prefix |
+-----+------------+
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Sudbeck |
| 222 | Farris |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Mandell |
| 218 | Neiman |
| 218 | Masada |
| 217 | Wendorf |
| 217 | Boudaillie |
| 216 | Cummings |
| 216 | Pettis |
| 216 | Solares |
+-----+------------+
15 rows in set (0.56 sec)
Đây là kết quả rất tốt. Điều này có nghĩa là chúng ta có thể tạo chỉ mục trên cột last_name
chỉ với 10 ký tự đầu tiên. Trong cột định nghĩa bảng last_name
được định nghĩa là VARCHAR(16)
và điều này có nghĩa là chúng tôi đã lưu 6 byte (hoặc nhiều hơn nếu có các ký tự UTF8 trong tên cuối cùng) cho mỗi mục nhập. Trong bảng này có 1637 giá trị riêng biệt nhân với 6 byte là khoảng 9KB và hãy tưởng tượng con số này sẽ tăng lên như thế nào nếu bảng của chúng tôi chứa hàng triệu hàng.
Bạn có thể đọc các cách tính số N khác trong bài viết của tôi Chỉ mục tiền tố trong MySQL .
UNIQUE
khóa?