趕著這幾天有些時間,把前段時間最佳化的幾條SQL經驗分享並總結下,以饗來者。第一個要分享的是對MyISAM最佳化limit分頁。背景來自公司某個業務系統提供給爬蟲抓取資料。基礎資訊:MySQL版本是5.1,引擎為MyISAM,原始SQL內容大致如下:註:為避免敏感資訊,將很多欄位變為col,但不影響閱讀 :-)
SELECT Aa.* , B.col, B.col, C.col, C.colFROM (SELECT A.col, A.col, A.col, A.col , A.col, A.col, A.col, A.col, A.col, A.col, A.col , A.col FROM A WHERE A.class1id = 1000000 AND 1 ORDER BY A.oktime DESC LIMIT 286660,20) AaLEFT JOIN B ON Aa.class2id=B.idLEFT JOIN C ON Aa.username=C.username
這已經是條最佳化過的SQL,我們觀察單次執行的影響:1. CPU抖動: 2. 執行時間: 單次執行情況貌似也不是嚴重,但這是爬蟲SQL,沒有規則可循,我們的長查詢警示郵件瘋狂拋出故需要再次對其最佳化,看下這個最佳化模型在MySQL裡面實際上很經典:ORDER BY desc/asc LIMIT x,y ,x很大我們認為它無法最佳化,是因為他是MyISAM,不是InnoDB,InnoDB在二級索引上會自動添加主鍵,但MyISAM不行。但我們認為它可以最佳化,也是因為他是MyISAM,我們可以類比InnoDB這個行為來最佳化
SELECT Aa.* , B.col, B.col, C.col, C.colFROM (SELECT A.col, A.col, A.col, A.col , A.col, A.col, A.col, A.col, A.col, A.col, A.col , A.col FROM A INNER JOIN (SELECT askid FROM solve_answerinfo use INDEX (idx_1) WHERE class1id = 1000000 ORDER BY oktime DESC LIMIT 389300,20) aaa USING (askid)) AaLEFT B ON Aa.class2id=B.idLEFT JOIN C ON Aa.username=C.username;
配套的索引策略:
create index idx_1 on solve_answerinfo (oktime,askid,class1id);
最佳化後的效果:1 cpu抖動 2 執行時間
具體的最佳化方法,可以參考我之前的文章:1 InnoDB二級索引自動添加主鍵 2 最佳化limit分頁
Good Luck!