2010-11-03 25 views
9

Tôi có một bảng MySQL:MySQL có thể sử dụng chỉ mục trong RANGE QUERY với ORDER BY không?

CREATE TABLE mytable (
    id INT NOT NULL AUTO_INCREMENT, 
    other_id INT NOT NULL, 
    expiration_datetime DATETIME, 
    score INT, 
    PRIMARY KEY (id) 
) 

tôi cần phải chạy truy vấn theo hình thức:

SELECT * FROM mytable 
WHERE other_id=1 AND expiration_datetime > NOW() 
ORDER BY score LIMIT 10 

Nếu tôi thêm chỉ số này để MyTable:

CREATE INDEX order_by_index 
ON mytable (other_id, expiration_datetime, score); 

Sẽ MySQL được có thể sử dụng toàn bộ số order_by_index trong truy vấn ở trên không? Có vẻ như nó sẽ có thể, nhưng sau đó theo số documentation của MySQL: "Chỉ mục cũng có thể được sử dụng ngay cả khi ORDER BY không khớp chính xác với chỉ mục, miễn là tất cả các phần chưa sử dụng của chỉ mục và tất cả các cột ORDER BY phụ khác là hằng số theo mệnh đề WHERE "

Đoạn trên dường như cho thấy chỉ mục sẽ chỉ được sử dụng trong truy vấn liên tục trong khi tôi là truy vấn phạm vi.

Có ai có thể làm rõ nếu chỉ mục sẽ được sử dụng trong trường hợp này không? Nếu không, bất kỳ cách nào tôi có thể buộc sử dụng chỉ mục?

Cảm ơn.

Trả lời

8

MySQL sẽ sử dụng chỉ mục để đáp ứng mệnh đề where và sẽ sử dụng tệp để đặt kết quả.

Không thể sử dụng chỉ mục cho đơn đặt hàng bởi vì bạn không so sánh ngày hết hạn với một hằng số. Do đó, các hàng được trả về sẽ không phải lúc nào cũng có tiền tố chung trong chỉ mục, vì vậy chỉ mục không thể được sử dụng cho sắp xếp.

Ví dụ, hãy xem xét một bộ mẫu hồ sơ 4 chỉ số cho bảng của bạn:

a) [1,'2010-11-03 12:00',1] 
b) [1,'2010-11-03 12:00',3] 
c) [1,'2010-11-03 13:00',2] 
d) [2,'2010-11-03 12:00',1] 

Nếu tôi chạy truy vấn của bạn tại 2010/11/03 11:00, nó sẽ trở lại hàng a, c, d không liên tiếp trong chỉ mục. Vì vậy, MySQL cần phải làm thêm pass để sắp xếp các kết quả và không thể sử dụng một chỉ mục trong trường hợp này.

+1

>> Nó không thể sử dụng các chỉ số cho thứ tự bởi vì bạn không so sánh expiration_datetime đến một hằng số. << Tôi nghĩ có một sai lầm ở đây. Bạn đã giải thích rõ nguyên nhân của điều đó trong phần thứ hai của câu trả lời. – kellogs

3

Có vẻ như bạn đã kiểm tra tài liệu và thiết lập chỉ mục. Sử dụng GIẢI THÍCH và xem ...

EXPLAIN SELECT * FROM mytable 
WHERE other_id=1 AND expiration_datetime > NOW() 
ORDER BY score LIMIT 10 
7

Có ai có thể làm rõ nếu chỉ mục sẽ được sử dụng trong trường hợp này không? Nếu không, bất kỳ cách nào tôi có thể buộc sử dụng chỉ mục?

Bạn có phạm vi trong điều kiện lọc và ORDER BY không khớp với phạm vi.

Những điều kiện này không thể được phân phát bằng một chỉ mục duy nhất.

Để chọn chỉ số để tạo, bạn cần phải chạy các truy vấn này

SELECT COUNT(*) 
FROM mytable 
WHERE other_id = 1 
     AND (score, id) < 
     (
     SELECT score, id 
     FROM mytable 
     WHERE other_id = 1 
       AND expiration_datetime > NOW() 
     ORDER BY 
       score, id 
     LIMIT 10 
     ) 

SELECT COUNT(*) 
FROM mytable 
WHERE other_id = 1 
     AND expiration_datetime >= NOW() 

và so sánh kết quả đầu ra của họ.

Nếu truy vấn thứ hai mang về cùng một hoặc nhiều giá trị như giá trị đầu tiên, thì bạn nên sử dụng chỉ mục trên (other_id, score) (và để nó lọc trên expiration_datetime).

Nếu truy vấn thứ hai mang lại giá trị ít hơn đáng kể so với giá trị đầu tiên, bạn nên sử dụng chỉ mục trên (other_id, expiration_datetime) (và để nó sắp xếp theo số score).

Bài viết này có thể là thú vị cho bạn:

+0

Để kiểm tra tính chọn lọc, bạn cần phải kiểm tra các giá trị khác biệt, vì vậy đừng quên thực hiện COUNT DISTINCT. –

+0

@AllTheCode: 'COUNT DISTINCT' về cái gì? – Quassnoi

Các vấn đề liên quan