的MySQL查詢望着查詢的EXPLAIN
計劃,一個人如何確定在何處的優化才能最好地做出?如何優化基於解釋計劃
我意識到的第一件事情要檢查一個是是否正在使用良好的指標,但除此之外,我有點爲難。通過過去的嘗試和錯誤,我有時會發現,進行連接的順序可能是一個很好的改進來源,但是如何通過查看執行計劃來確定?
雖然我非常希望獲得對如何優化查詢的好大致的瞭解(建議閱讀非常感謝!),我也認識到,它往往更容易討論比抽象的談具體案例。由於我目前撞我的頭這一個牆,您的想法將是非常讚賞:
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
上午我在解釋執行計劃的最後一行更正如下:
- 爲它的主鍵完全匹配,每個輸出行只需要獲取一行
R2
; - 然而,這樣的輸出行然後基於應用於
R2
某些標準過濾?
如果是這樣,我的問題在於最後一步發生的過濾。如果條件不進行過濾(例如WHERE `Col_1_to_3` IN (1,2,3)
),則查詢運行速度非常快(〜50ms)。但是,如果條件限制所選的行(WHERE `Col_1_to_3` IN (1,2)
),則查詢需要相當長的時間(〜5秒)。如果限制爲單一匹配(WHERE `Col_1_to_3` IN (1)
),優化器會提出一個完全不同的執行計劃(其執行效果略好於5s,但仍比50ms差很多)。看起來好像沒有更好的索引可以用於該表(因爲它已經完全使用主鍵來爲每個結果返回一行)。
一個應該如何解讀這些信息?我是否猜測,因爲這樣的輸出過濾發生在要加入的最終表上,相對於之前加入表格並過早過濾這些行而言,會付出相當大的努力呢?如果是這樣,如何確定執行計劃R2
何時應該加入?
雖然我拒絕了,包括在這裏充分查詢&架構(如我真的很容易知道該找什麼,而不是僅僅被告知的答案),我明白有必要提前討論:
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
;
表R
的定義是:
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
你介意顯示查詢嗎? – 2012-04-13 22:04:31
@MarcusAdams:我不介意*,但你會找什麼?我覺得如果我知道你會看到什麼,我可能會學到更多... – eggyal 2012-04-13 22:07:53
你指的是col_1_to_3,但我在EXPLAIN結果中看不到這樣的列。如果您可以對問題進行短語說明,只是說明問題,換句話說,刪除討論查詢的段落,那麼我們不需要查詢,答案是肯定的。一般來說,我們需要查詢,模式和解釋,否則我們猜測。 – 2012-04-13 22:12:31