我無法通過MySQL InnoDB優化器優化請求。 下面的查詢(查詢1)高效運行:MySQL InnoDB採取的執行計劃效率不高
explain select * from ah_problems
where rnid in (6022342, 6256614, 5842714, 6302489)
and fieldid in (5,6);
和計劃(方案1)如下:
id select_type table type possible_keys key key_len ref rows Extra
= ====== =========== ===== =============================== ============= ======= === ==== =====
1 SIMPLE ah_problems range CONSTRAINTFIELDID,RNID__FIELDID RNID__FIELDID 8 33 Using where
到目前爲止,一切都很好。
儘管稍微修改查詢(查詢2)下面將採取災難性的執行計劃:
explain select * from ah_problems
where rnid in (select rec.rnid as record_id from ar_records rec where rnid in (6022342, 6256614, 5842714, 6302489))
and fieldid in (5, 6)
的結果是一樣的,但是計劃(方案2)現在是這樣做的:
id select_type table type possible_keys key key_len ref rows Extra
= ====== =========== ===== ================== ======== ======= ==== ======= =====
1 PRIMARY ah_problems ALL CONSTRAINTFIELDID 36177754 Using where
2 DEPENDENT SUBQUERY rec unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
如果你想知道,新的子查詢...
select rec.rnid as record_id from ar_records rec where rnid in (6022342, 6256614, 5842714, 6302489)
...沒有什麼比返回四個R更在查詢1中硬編碼的行:
6022342
6256614
5842714
6302489
因此查詢(1)和(2)是等價的。
猜猜看,我需要查詢2,而不是一個。我想查詢2是作爲查詢1.我嘗試以下高效:
查詢3:添加
FORCE INDEX(RNID_FIELDID)
查詢2. MySQL的只是忽略它。解釋SELECT * FROM ah_problems力指數(rnid__fieldid) 其中RNID在(從ar_records REC選擇rec.rnid作爲RECORD_ID其中RNID在(6022342,6256614,5842714,6302489)) 和fieldid在(5,6)
執行計劃是一樣的規劃2.
查詢4:添加
ORDER BY RNID, FIELDID
查詢3.我的一些其他問題看到,這可能會誘使優化。它沒有幫助。解釋SELECT * FROM ah_problems力指數(rnid__fieldid) 其中RNID在(從ar_records REC選擇rec.rnid作爲RECORD_ID其中RNID在(6022342,6256614,5842714,6302489)) 和fieldid在(5,6)爲了通過RNID,fieldid
計劃4現在使用的索引,但行數仍然是災難性的:
id select_type table type possible_keys key key_len ref rows Extra
= ====== =========== ===== ================== ======== ======= ==== ======= =====
1 PRIMARY ah_problems index RNID__FIELDID 8 36179307 Using where
2 DEPENDENT SUBQUERY rec unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
如果這會有所幫助,這是我ah_problems
表的定義。很遺憾,我無法改變表格的定義。有什麼我可以做的,使MySQL優化器使用計劃1攻擊查詢2中的表ah_problems
?
CREATE TABLE `ah_problems` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Identifier for update statements',
`RNID` int(11) NOT NULL COMMENT 'Record number',
`FIELDID` int(11) NOT NULL COMMENT 'Which field is value in',
`VALUE` varchar(255) NOT NULL COMMENT 'The value the field got on MODIFIED_DATE',
`PREVIOUSID` int(11) DEFAULT NULL COMMENT 'Reference to previous value',
`MODIFIED_DATE` datetime NOT NULL COMMENT 'When was it changed',
`MODIFIED_GROUPID` int(11) DEFAULT NULL COMMENT 'In what group did modified_userid change it',
`MODIFIED_USERID` int(11) NOT NULL COMMENT 'Who changed it',
PRIMARY KEY (`ID`),
KEY `CONSTRAINTFIELDID` (`FIELDID`),
KEY `CONSTRAINTMODIFIED_GROUPID` (`MODIFIED_GROUPID`),
KEY `CONSTRAINTMODIFIED_USERID` (`MODIFIED_USERID`),
KEY `CONSTRAINTPREVIOUSID` (`PREVIOUSID`),
KEY `RNID__FIELDID` (`RNID`,`FIELDID`),
CONSTRAINT `HPRB_FIELD` FOREIGN KEY (`FIELDID`) REFERENCES `ad_fields` (`ID`),
CONSTRAINT `HPRB_MODIFIED_GROUP` FOREIGN KEY (`MODIFIED_GROUPID`) REFERENCES `ap_groups` (`ID`),
CONSTRAINT `HPRB_MODIFIED_USER` FOREIGN KEY (`MODIFIED_USERID`) REFERENCES `ap_users` (`ID`),
CONSTRAINT `HPRB_PREVIOUS` FOREIGN KEY (`PREVIOUSID`) REFERENCES `ah_problems` (`ID`) ON DELETE CASCADE,
CONSTRAINT `HPRB_RN` FOREIGN KEY (`RNID`) REFERENCES `ar_records` (`RNID`)
) ENGINE=InnoDB AUTO_INCREMENT=72305308 DEFAULT CHARSET=utf8 COMMENT='PTR history'$$
如果查詢1和2是等價的,那麼你一定不能被利用工作爲你如果查詢1不起作用,就寫它。是否有一些問題阻止了1的工作?任何信息可能有助於提供更好的答案 – dlp 2013-04-30 16:53:15
查詢1有效。查詢2有效,但速度很慢。實際上,這兩個查詢都試圖找出優化器的問題。我的實際查詢實際上更復雜(添加的子查詢動態獲取要獲取的記錄列表)。 – 2013-04-30 16:56:15