2012-04-13 36 views
19

Nhìn vào kế hoạch EXPLAIN của truy vấn, làm cách nào để xác định nơi tối ưu hóa tốt nhất có thể được thực hiện?Cách tối ưu hóa truy vấn MySQL dựa trên kế hoạch GIẢI THÍCH

Tôi đánh giá cao rằng một trong những điều đầu tiên cần kiểm tra là liệu các chỉ mục tốt có đang được sử dụng hay không, nhưng ngoài ra, tôi hơi bối rối. Qua thử thách và sai lầm trong quá khứ, đôi khi tôi thấy rằng thứ tự mà việc tham gia được tiến hành có thể là một nguồn cải tiến tốt, nhưng làm sao người ta có thể xác định rằng khi nhìn vào kế hoạch thực hiện?

Mặc dù tôi rất muốn hiểu rõ về cách tối ưu hóa các truy vấn (gợi ý đọc nhiều đánh giá!), Tôi cũng nhận ra rằng việc thảo luận các trường hợp cụ thể thường dễ hơn là nói tóm tắt. Vì tôi hiện đang đập đầu tôi vào tường với một này, suy nghĩ của bạn sẽ được nhiều đánh giá cao:

 
id select_type table type  possible_keys key  key_len ref     rows Extra 
1 SIMPLE  S  const PRIMARY,l,p,f4 PRIMARY   2 const      1 Using temporary 
1 SIMPLE  Q  ref  PRIMARY,S  S    2 const     204 Using index 
1 SIMPLE  V  ref  PRIMARY,n,Q  Q    5 const,db.Q.QID   6 Using where; Using index; Distinct 
1 SIMPLE  R1  ref  PRIMARY,L  L    154 const,db.V.VID   447 Using index; Distinct 
1 SIMPLE  W  eq_ref PRIMARY,w  PRIMARY   5 const,db.R.RID,const  1 Using where; Distinct 
1 SIMPLE  R2  eq_ref PRIMARY,L  PRIMARY  156 const,db.W.RID,const  1 Using where; Distinct 

Am I correct trong việc giải thích dòng cuối cùng của kế hoạch thực hiện như sau:

  • như nó được khớp hoàn toàn trên khóa chính của nó, chỉ cần một hàng của R2 được tìm nạp trên mỗi hàng đầu ra; Tuy nhiên,
  • tuy nhiên, các hàng đầu ra như vậy sau đó được lọc dựa trên một số tiêu chí áp dụng cho R2?

Nếu vậy, sự cố của tôi nằm trong quá trình lọc xảy ra ở bước cuối cùng đó. Nếu điều kiện không dẫn đến lọc (ví dụ: WHERE `Col_1_to_3` IN (1,2,3)), truy vấn sẽ chạy cực nhanh (~ 50ms); tuy nhiên, nếu điều kiện hạn chế các hàng được chọn (WHERE `Col_1_to_3` IN (1,2)), truy vấn sẽ mất nhiều thời gian hơn (~ 5s). Nếu hạn chế là một trận đấu đơn lẻ (WHERE `Col_1_to_3` IN (1)), trình tối ưu hóa đề xuất một kế hoạch thực hiện hoàn toàn khác (hoạt động tốt hơn 5 lần, nhưng vẫn còn tồi tệ hơn 50ms). Nó không có vẻ như là có một chỉ số tốt hơn có thể được sử dụng trên bảng đó (cho nó đã hoàn toàn bằng cách sử dụng khóa chính để trả về một hàng cho mỗi kết quả?).

Làm cách nào để giải thích tất cả thông tin này? Tôi có đoán được điều đó không, bởi vì việc lọc đầu ra như vậy đang diễn ra trên bảng cuối cùng để được tham gia, nỗ lực đáng kể bị lãng phí so với việc gia nhập bảng trước đó và lọc các hàng như vậy sớm hơn? Nếu vậy, làm thế nào để xác định khi nào trong kế hoạch thực hiện R2 nên được tham gia?

Trong khi tôi phản đối bao gồm các lược đồ truy vấn & đầy đủ ở đây (như tôi sẽ thực sự có khả năng biết phải tìm kiếm, không chỉ đơn thuần được cho biết câu trả lời), tôi hiểu đó là cần thiết để thúc đẩy các cuộc thảo luận:

SELECT DISTINCT 
    `Q`.`QID` 
FROM 
    `S` 
    NATURAL JOIN `Q` 
    NATURAL JOIN `V` 
    NATURAL JOIN `R` AS `R1` 
    NATURAL JOIN `W` 

    JOIN `R` AS `R2` ON (
      `R2`.`SID` = `S`.`SID` 
     AND `R2`.`RID` = `R1`.`RID` 
     AND `R2`.`VID` = `S`.`V_id` 
     AND `R2`.`Col_1_to_3` IN (1,2) -- this is where performance suffers! 
    ) 

WHERE 
    AND `S`.`SID` = @x 
    AND `W`.`WID` = @y 
; 

định nghĩa của bảng R là:

CREATE TABLE `R` (
    `SID` smallint(6) unsigned NOT NULL, 
    `RID` smallint(6) unsigned NOT NULL, 
    `VID` varchar(50) NOT NULL DEFAULT '', 
    `Col_1_to_3` smallint(1) DEFAULT NULL, 
    `T` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`SID`,`RID`,`VID`), 
    KEY `L` (`SID`,`VID`,`Col_1_to_3`), 
    CONSTRAINT `R_f1` FOREIGN KEY (`SID`) REFERENCES `S` (`SID`), 
    CONSTRAINT `R_f2` FOREIGN KEY (`SID`, `VID`) REFERENCES `V` (`SID`, `VID`), 
    CONSTRAINT `R_f3` FOREIGN KEY (`SID`, `VID`, `Col_1_to_3`) REFERENCES `L` (`SID`, `VID`, `LID`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 
+0

Bạn cũng có phiền khi hiển thị truy vấn không? –

+0

@MarcusAdams: Tôi không * quan tâm *, nhưng bạn sẽ tìm kiếm điều gì? Tôi cảm thấy rằng tôi có khả năng tìm hiểu thêm nếu tôi biết bạn đang xem cái gì ... – eggyal

+0

Bạn tham khảo col_1_to_3, nhưng tôi không thấy một cột như vậy trong kết quả GIẢI THÍCH. Nếu bạn có thể cụm từ câu hỏi để nó chỉ là về giải thích, nói cách khác loại bỏ các đoạn nói về truy vấn, sau đó chúng ta không cần truy vấn, và câu trả lời là có. Nói chung, chúng tôi cần truy vấn, lược đồ và giải thích, nếu không chúng tôi sẽ đoán. –

Trả lời

13

Phụ thuộc vào những gì bạn đang đi và những gì các truy vấn được.

Nói chung, đối với mỗi dòng trong GIẢI THÍCH rằng có Using where, bạn cần có nó bằng cách sử dụng chỉ mục (possible keyskeys cột). Đây là các bộ lọc của bạn và bao gồm WHERE và ON. Có nó nói Using index thậm chí còn tốt hơn. Nó có nghĩa là có một chỉ số bao gồm, và MySQL có thể lấy dữ liệu ngay từ chỉ mục thay vì truy cập hàng trong dữ liệu bảng.

Các dòng nơi không có Using where và đang trả về một số lượng lớn hàng nên được xem xét.Đây là các giá trị trả lại cho tất cả các hàng trong bảng. Tôi không biết truy vấn của bạn là gì, vì vậy tôi không biết có nên báo động ở đây không. Thử lọc tập hợp kết quả để giảm kích thước và cải thiện hiệu suất.

Bạn thường cố gắng tránh nhìn thấy Using filesort hoặc Using temporary, mặc dù những điều đó chỉ xấu nếu bạn không mong đợi chúng.

Tệp tin thường xuất hiện với mệnh đề ORDER. Nói chung, bạn muốn MySQL sử dụng chỉ mục bao phủ (Using index) để các hàng được trả về theo thứ tự từ máy chủ. Nếu không, sau đó MySQL phải đặt hàng chúng sau đó, bằng cách sử dụng filesort.

Using temporary có thể xấu khi nó đề cập đến các bảng có nguồn gốc vì chúng không có chỉ mục. Có vẻ như bạn đã tạo một bảng tạm thời với các chỉ mục, vì vậy ở đây, nó không phải là xấu. Đôi khi, lựa chọn duy nhất của bạn là sử dụng một bảng có nguồn gốc, và do đó Using temporary.

+0

Cảm ơn Marcus. Tôi cho rằng những gì tôi thấy kỳ quặc nhất là sự khác biệt đáng kể về hiệu suất phát sinh từ một bộ lọc trên bảng cuối cùng; do đó có vẻ như vấn đề không nằm trong "dòng nơi ... nó đang trả lại một số lượng lớn hàng", mà bạn đề nghị tôi xem xét? – eggyal

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