Chỉ số bao phủ được sử dụng mặc dù thiếu cột


8

Tôi có truy vấn sau, sử dụng MariaDB 10 / InnoDB:

SELECT id, sender_id, receiver_id, thread_id, date_created, content 
FROM user_message 
WHERE thread_id = 12345 
  AND placeholder = FALSE
ORDER BY date_created DESC 
LIMIT 20

Truy vấn này tìm nạp thư theo các điều kiện đã cho và sắp xếp theo ngày được tạo.

Tôi có một chỉ số bao gồm hơn (thread_id, date_created).

Khi chạy EXPLAIN, chỉ mục chính xác được sử dụng và tôi nhận được đầu ra "Sử dụng ở đâu", mặc dù truy vấn đang sử dụng một cột ở giữa câu lệnh không có trong chỉ mục. Tôi có thể sử dụng bất kỳ giá trị nào cho "giữ chỗ = x" và kết quả là như nhau.

Nếu tôi thay đổi cách sắp xếp để sử dụng một cột khác, thì GIẢI THÍCH chính xác cho biết "Sử dụng ở đâu. Sử dụng tệp."

Tôi đang có một khoảnh khắc đau đầu. Bất cứ ai có thể làm sáng tỏ về điều này? Những gì tôi mong đợi sẽ thấy là một tập tin bổ sung sẽ là cần thiết vì chỉ số bao phủ không thể được sử dụng hoàn toàn do cột bổ sung.

Câu trả lời:


8

Trường hợp A
Truy vấn:

WHERE thread_id = 12345 
  AND placeholder = FALSE
ORDER BY some_column DESC 
LIMIT 20

Mục lục:

(thread_id, date_created)

Kế hoạch:

Index is used
Using Where
Using filesort

Không có vấn đề ở đó, phải không? Nếu chỉ mục được sử dụng (để khớp một phần với WHEREđiều kiện), chúng ta vẫn cần một thao tác sắp xếp để sắp xếp các kết quả theo some_column(không nằm trong chỉ mục). Chúng tôi cũng cần kiểm tra thêm (Sử dụng ở đâu) để chỉ giữ các hàng khớp với điều kiện thứ 2. ĐỒNG Ý.


Trường hợp B (câu hỏi)
Truy vấn:

WHERE thread_id = 12345 
  AND placeholder = FALSE
ORDER BY date_created DESC 
LIMIT 20

Mục lục:

(thread_id, date_created)

Kế hoạch:

Index is used
Using Where
-- no "Using filesort"

Vì vậy, tại sao nó không cần một loại ở đây ? Bởi vì chỉ mục là đủ để sắp xếp như truy vấn muốn. Tất nhiên có vấn đề bổ sung của điều kiện bổ sung ( AND placeholder = FALSE) không được bao phủ bởi chỉ số.

OK nhưng chúng tôi không thực sự cần một loại ở đây. Chỉ mục có thể cung cấp cho chúng tôi các kết quả khớp với điều kiện đầu tiên ( WHERE thread_id = 12345) và theo thứ tự mong muốn cho đầu ra. Kiểm tra bổ sung duy nhất chúng tôi cần - và những gì kế hoạch thực hiện - là lấy các hàng từ bảng, theo thứ tự được cung cấp bởi chỉ mục và kiểm tra điều kiện thứ 2 này cho đến khi chúng tôi nhận được 20 kết quả khớp. Đó là những gì ** Sử dụng "" có nghĩa là gì.

Chúng tôi có thể nhận được 20 trận đấu trong 20 hàng đầu tiên (rất tốt và nhanh) hoặc trong 100 trận đầu tiên (vẫn có thể đủ nhanh) hoặc trong 1000000 đầu tiên (có thể rất, rất chậm) hoặc chúng tôi có thể chỉ nhận được 19 trận đấu từ bảng ngay cả sau khi đọc tất cả các hàng khớp từ chỉ mục (thực sự rất chậm trên một bảng lớn). Tất cả phụ thuộc vào việc phân phối dữ liệu.



Truy vấn trường hợp C (kế hoạch thậm chí tốt hơn) :

WHERE thread_id = 12345 
  AND placeholder = FALSE
ORDER BY date_created DESC 
LIMIT 20

Mục lục:

(placeholder, thread_id, date_created)

Kế hoạch:

Index is used
-- no "Using Where"
-- no "Using filesort"

Bây giờ chỉ số của chúng tôi phù hợp với cả hai điều kiện và thứ tự của. Kế hoạch khá đơn giản: lấy * 20 trận đấu đầu tiên từ chỉ mục và đọc các hàng tương ứng từ bảng. Không cần kiểm tra thêm (Không "Sử dụng ở đâu") và không cần sắp xếp (không "Sử dụng tập tin").

đầu tiên *: 20 đầu tiên khi đọc chỉ mục ngược từ cuối (như chúng ta có ORDER BY .. DESC) nhưng đó không phải là vấn đề. Chỉ số cây B có thể được đọc tiến và lùi với hiệu suất gần như bằng nhau.


7
  • Sử dụng chỉ số cho thấy một " Bao gồm chỉ số" - Tất cả các cột bất cứ nơi nào trong SELECTbất cứ nơi nào trong chỉ mục một. Vì vậy, bạn không có chỉ số "bao phủ". Và nó không thực tế để tạo một chỉ mục bao phủ cho truy vấn của bạn (quá nhiều cột được đề cập).
  • Sử dụng ở đâu - chủ yếu là tiếng ồn.
  • Sử dụng filesort - Truy vấn cần sắp xếp, nhưng nó có thể nằm trong RAM hoặc trong bảng tạm thời. Và có thể có nhiều loại (ví dụ, GROUP BY x ORDER BY b)
  • Một trong hai điều này sẽ làm cho nó chỉ có thể nhìn vào 20 hàng; bất kỳ chỉ mục nào khác sẽ yêu cầu nhiều hàng hơn được chạm vào, có thể là toàn bộ bảng:

    INDEX(thread_id, placeholder, date_created)
    INDEX(placeholder, thread_id, date_created)
  • Không, tính chính xác của các thành phần của một chỉ mục tổng hợp không quan trọng khi sắp xếp các cột trong chỉ mục.

My Cookbook giải thích làm thế nào để lấy được chỉ số tối ưu, đưa ra a SELECT.


Cảm ơn cuốn sách nấu ăn - tờ rất đẹp.
Tom
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.