2012-12-16 33 views
5

Tôi có một câu hỏi ví dụ như:Loại chỉ mục nào lý tưởng cho truy vấn này?

SELECT 
    rest.name, rest.shortname 
FROM 
    restaurant AS rest 
    INNER JOIN specials ON rest.id=specials.restaurantid 
WHERE 
    specials.dateend >= CURDATE() 
AND 
    rest.state='VIC' 
AND 
    rest.status = 1 
AND 
    specials.status = 1 
ORDER BY 
    rest.name ASC; 

Chỉ cần tự hỏi trong những dưới hai chỉ số, đó sẽ là tốt nhất trên bàn nhà hàng?

id,state,status,name 
state,status,name 

Bạn không chắc chắn nếu cột được sử dụng trong tham gia phải được bao gồm?

Vui đủ, mặc dù tôi đã tạo cả hai loại để thử nghiệm và cả hai lần MySQL chọn chỉ số chính, chỉ là id. Tại sao vậy?

Giải thích Output:

1,'SIMPLE','specials','index','NewIndex1\,NewIndex2\,NewIndex3\,NewIndex4','NewIndex4','11',\N,82,'Using where; Using index; Using temporary; Using filesort', 
1,'SIMPLE','rest','eq_ref','PRIMARY\,search\,status\,state\,NewIndex1\,NewIndex2\,id-suburb\,NewIndex3\,id-status-name','PRIMARY','4','db_name.specials.restaurantid',1,'Using where' 

Không nhiều hàng vào lúc này vì vậy có lẽ đó là lý do tại sao nó được chọn TIỂU !?

+0

Bạn luôn có thể sử dụng 'GIẢI THÍCH ' để nhận một số thông tin về cách truy vấn chọn sẽ được thực thi. http://dev.mysql.com/doc/refman/5.0/en/using-explain.html – Cyclonecode

+0

Tôi đã làm, đó là cách tôi phát hiện ra nó đang sử dụng chỉ mục 'PRIMARY', chỉ chứa cột' id'. – Brett

+0

Bạn có thể yêu cầu xuất bản giải thích đầy đủ và phiên bản MySQL không? –

Trả lời

2

Đối với hiệu suất tối ưu, bạn cần ít nhất 2 chỉ số:

Chỉ số quan trọng nhất là một trong những ngày quan trọng nước ngoài:

CREATE INDEX specials_rest_fk ON specials(restaurantid); 

Nếu không có này, truy vấn của bạn sẽ hoạt động kém, bởi vì mỗi hàng trong rest khớp với điều kiện WHERE sẽ yêu cầu một bảng đầy đủ của specials.

Chỉ mục tiếp theo để xác định sẽ là chỉ mục giúp tìm kiếm các hàng ít nhất là rest với điều kiện của bạn. Chỉ có một chỉ mục được sử dụng, vì vậy bạn muốn làm cho chỉ mục đó tìm thấy một vài hàng từ rest nhất có thể.

tôi đoán, tiểu bang và địa vị:

CREATE INDEX rest_index_1 on rest(state, status); 

đề nghị chỉ số của bạn trong (id, ...) là vô nghĩa, bởi vì id là duy nhất - thêm cột hơn sẽ không giúp đỡ, và trong thực tế sẽ xấu đi hiệu suất nếu nó được sử dụng, bởi vì các mục chỉ mục sẽ lớn hơn và bạn sẽ nhận được ít mục nhập hơn cho mỗi trang I/O đọc.

Nhưng bạn cũng có thể đạt được hiệu suất bằng cách viết truy vấn tốt hơn; nếu bạn di chuyển các điều kiện đặc biệt vào điều kiện tham gia ON, bạn sẽ đạt được hiệu suất đáng kể, vì điều kiện kết nối được đánh giá khi kết nối được thực hiện, nhưng điều kiện được đánh giá trên tất cả các hàng được nối, nghĩa là tập kết quả tạm thời được lọc bởi mệnh đề WHERE lớn hơn nhiều và do đó chậm hơn.

Thay đổi truy vấn của bạn như thế này:

SELECT rest.name, rest.shortname 
FROM restaurant AS rest 
INNER JOIN specials 
    ON rest.id=specials.restaurantid 
    AND specials.dateend >= CURDATE() 
    AND specials.status = 1 
WHERE rest.state='VIC' 
AND rest.status = 1 
ORDER BY rest.name; 

Lưu ý cách các điều kiện về sản phẩm đặc biệt hiện nay có trong mệnh đề ON.

+0

Vâng, tôi đã có chỉ mục được tạo trên 'restaurantid' trên bảng đặc biệt. – Brett

+0

Xem câu trả lời đã chỉnh sửa – Bohemian

+0

Cảm ơn bạn rất nhiều! Không biết bạn có thể làm điều đó với JOIN. Vài câu hỏi mặc dù - với chỉ mục bạn đã tạo trên 'phần còn lại '; không thêm trạng thái 'vô nghĩa 'vì bản thân thẻ quá thấp? ... hoặc sẽ không thêm 'tên' vào sự giúp đỡ cuối cùng cũng như nhìn thấy như nó đang ở trong' ORDER BY'? – Brett

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