原sql:
SELECT res_id_ori FROM wk_sheet A, wk_page b WHERE A .wk_sheet_id = b.wk_sheet_id AND b.res_id_ori IN ('919844276962074624','919856729196335104','926389611062652928','914850828240564224','914850835693834240','914850844854202368','914850876089176064','914850863539826688') and a.status = -999 and a.scan_status = 3 ;
原sql執行計划:
Planning time: 0.145 ms Execution time: 1313.189 ms
優化方案:創建聯合索引
create index idx_residori_sheetid on wk_page(res_id_ori,wk_sheet_id);
sql執行計划:
EXPLAIN (analyze,verbose,timing,costs,buffers) SELECT res_id_ori FROM wk_sheet A, wk_page b WHERE A .wk_sheet_id = b.wk_sheet_id AND b.res_id_ori IN ('919844276962074624','919856729196335104','926389611062652928','914850828240564224','914850835693834240','914850844854202368','914850876089176064','914850863539826688') and a.status = -999 and a.scan_status = 3 ;
--優化效果
Planning time: 0.203 ms
Execution time: 123.095 ms
聯合索引,res_id_ori 由於它in數量少,建議做聯合索引前綴;要是res_id_ori太多也會走全表掃碼。(wk_sheet_id做前綴比res_id_ori 做前綴慢個200ms,這個需要根據具體情況 具體分析)
總結:
1.把合適的業務字段作為主鍵字段,如果沒有合適的就選擇從1自增的非業務字段作為主鍵字段
2.通過explain 檢驗新上線sql性能以及診斷優化慢查詢
3.關於關聯查詢的建議就是在每個表的關聯字段上都要創建索引
4.全表掃描時, 需要在where條件上選擇性高的單字段或組合字段上創建索引避免全表掃描
5.如何創建聯合索引:
如果其中有一個字段的選擇性高達80%就只需在此字段上創建索引;如果沒有選擇性高過50%的字段則選擇創建聯合索引 如果創建聯合索引,應該將哪個字段作為前綴索引,結合兩個指標 :
1、選擇高頻出現的字段作為聯合索引前綴列 相比於上面的sql,有另一個sql :select * from t1 where col2=2;只以col2作為條件,這種情況下就將col2作為前綴索引,因為這樣可以使得兩個sql都會用到聯合索引idx_col2_col3
2、如果沒有情況1,則選擇選擇性最高的字段作為前綴;且都需通過 select count(distinct col1,col2...)/count(*) from t;來選擇一種選擇性最高的組合來創建聯合索引
其他mysql sql優化也是一樣的。