Bạn không thể mong đợi nhiều hơn một cột được tìm kiếm qua chỉ mục cho các biến vị ngữ phạm vi như IN
.
Thậm chí nếu bạn có một chỉ số nhiều cột (a, b, c, d, date), các cột tận cùng bên trái nên được cho bình đẳng predicates (=
) và nhiều nhất là một cột có thể dành cho một vị tầm xa. Bất kỳ cột tiếp theo nào trong chỉ mục đều không hữu ích.
Ví dụ:
WHERE a = 2884 AND b = 'b' AND c IN (1, 2, 3) AND d = 'abcd'
Vì vậy a
và b
là vị bình đẳng, c
là một vị phạm vi, và d
là một vị bình đẳng.
Chạy GIẢI THÍCH trên truy vấn và lưu ý các cột len
và ref
cho biết rằng bạn chỉ đang sử dụng hai cột đầu tiên của chỉ mục. Điều kiện cho d
được thực hiện một cách khó khăn, bằng cách tìm kiếm tất cả các hàng được tìm thấy bởi chỉ mục trên ba cột đầu tiên.
id: 1
select_type: SIMPLE
table: t
type: ref
possible_keys: a
key: a
key_len: 7 <--- two columns' length
ref: const,const <--- only two values for index columns `a` and `b`
rows: 4
Extra: Using where; Using index
Trong khi thay đổi c
đến một vị bình đẳng cho phép tất cả bốn cột được sử dụng để tra cứu chỉ số:
WHERE a = 2884 AND b = 'b' AND c = 2 AND d = 'abcd'
id: 1
select_type: SIMPLE
table: t
type: ref
possible_keys: a
key: a
key_len: 25 <--- four columns' length
ref: const,const,const,const <--- four values
rows: 2
Extra: Using where; Using index
tôi nói về chi tiết này trong bài trình bày của tôi How to Design Indexes, Really.
Re bình luận của bạn:
là có cách nào để khắc phục điều này mà không cần phải viết lại mã?
Bạn có điểm rằng bạn chỉ có thể có một biến vị ngữ là có lợi từ chỉ mục. Bạn vẫn có thể có các biến vị ngữ khác trong mệnh đề WHERE của bạn, nhưng chúng không nhận được bất kỳ lợi ích nào từ một chỉ mục.
Nhưng đó không phải là công cụ giải quyết thỏa thuận, bởi vì nếu biểu thức một phạm vi bạn lập chỉ mục có thể giúp thu hẹp tìm kiếm xuống 99%, đó là chiến thắng. Sau đó, áp dụng các biểu thức khác cho các hàng phù hợp là chi phí chúng ta có thể sử dụng.
Trình tối ưu hóa sẽ cố gắng chọn chỉ mục hiệu quả nhất nếu có thể và điều này phần lớn chịu ảnh hưởng của chỉ số chọn lọc. Sau đó truy vấn sử dụng chỉ mục để thu hẹp tìm kiếm và chỉ tập hợp con các hàng vượt qua tìm kiếm đó được thử nghiệm với các điều kiện khác.
Đi khác nhìn vào truy vấn của bạn:
... WHERE
a IN (2884,5320)
AND
b IN ('a', 'b', 'c')
AND
c IN (1, 2, 3)
AND d='abcd'
AND date BETWEEN 0 AND 1383177599
Giả sử chúng ta biết rằng chỉ có 1% của các hàng phù hợp c IN (1,2,3)
, nhưng các điều khoản khác phù hợp hơn như 20-40% của các hàng trên trung bình.
Chúng tôi có thể lập chỉ mục cho vị từ bình đẳng, điều đó là ổn. Sau đó, chúng tôi sẽ chọn một cột khác cho chỉ mục vì tất cả các cụm từ khác là các biến vị ngữ phạm vi. Chúng tôi chọn cột được chọn lọc nhất: c
. Do đó, chỉ mục tốt nhất là trên (d, c) và phải là theo thứ tự đó.
Bạn có thể có các truy vấn khác trong ứng dụng có các lựa chọn khác nhau cho các cột được tham chiếu trong mệnh đề WHERE và giá trị cụ thể mà chúng tôi đang tìm kiếm. Vì vậy, chúng tôi có thể cần một chỉ mục khác với một tập hợp các cột khác nhau hoặc thậm chí các cột giống nhau theo một thứ tự khác. Không cần nhiều chỉ mục, vì như tôi đã đề cập trong bản trình bày, các chỉ mục bạn cần tạo phụ thuộc vào các truy vấn bạn muốn tối ưu hóa.
Bạn có thể hiển thị kết quả giải thích không? – Ashalynd
Yup, được thêm vào câu hỏi @Ashalynd – cmwright