一 簡介:此文章為經歷過的sql案例集合和相關思路
二 案例1:
現象: 測試環境出現select語句,join2張表多次join,explain結果如下 出現 using where,using join buffer (block nested loop)
思路分析:bnl 5.6優化,首先就看連線字段是否有索引(也有可能有索引沒加上),發現沒有索引
解決辦法: 連線字段加上索引,問題解決(是不是很簡單)
案例2
現象:線上出現select併發語句,語句比較複雜,就不貼出來了
思路分析:explain下發現多個join後面的連線字段沒有索引
解決辦法:連線字段加上索引,問題解決
案例3select * from a where ctime <= date_format(date_add(sysdate(), interval - 30 day), '%y-%m-%d')
現象: 此語句全表掃瞄
思路分析: 很奇怪的語句,ctime有索引,而且函式並沒有作用於索引本身,為什麼不走索引呢,嘗試用字串日期代替函式本身,explain下是走索引的,問題出現在函式這塊
解決辦法: 將sysdate去掉,用now取代,explain下發現,已經走索引
補充sysdate和now的區別
1 select sysdate(),sleep(2),sysdate() select now(),sleep(2),now()
sysdate獲取當時實時的時間,在語句執行中是不斷變化
now()取的是語句開始執行的時間,在整個語句執行過程中都不會變化。
2 sysdate在函式計算中不走索引,now可以走索引,前提這個時間字段本身是索引項
3 選擇sysdate可能導致主從同步問題
建議 在mysql語句中建議採用now函式
案例 4
select * from table where id in ( id1 ,id 2,。。。)
現象 查詢很慢,id存在索引,但是並沒有走
思路分析:由於此表資料量大,可能存在因為資料量導致的索引失效問題,所以採用 force index進行嘗試
解決辦法: 採用force index方式進行查詢
補充: explain下的force index出現了失真,掃瞄行數居然是表資料量的幾倍,暫時沒找到原因,所以,不要過分依賴explain的結果,自己去查詢試試
案例5
select * from table where a='' order by b
現象 已經建立了 a和b的聯合索引,依然出現了file sort檔案排序
思路分析: 調出表結構發現 a varchar(200) b varchar(300),遠遠超過了5.6規定的767位元組,那為什麼還能建立成功呢,原來5.7已經放開了限制,已經調大到3000+.但是依然只能用到字首索引
解決辦法: 縮短字段長度,盡量索引長度不要超過767字元
補充: 5.7雖然放開了索引長度的限制,但是毫無意義,也請大家盡量規範好字串的長度,防止發生上述問題
案例6
select * from table where a= b= order by c
現象 已經建立了 a c 聯合索引 ,但是效率很低
思路分析: 首先通過explain發現,掃瞄行數並不多 也就3w多行,但是令人奇怪的是,建立了a c聯合的索引,卻只用到了a,而且extra中並沒有出現檔案排序
解決方法: 建立 a b c三者的聯合索引。
總結:不要單單看掃瞄行數少就認為不要優化,讓sql走正確的索引,去掉不正確的,這也是乙個非常重要的原則
案例7
select * from table where a in () and b > ' ' order by b desc
索引情況 (a b) (b a) 聯合索引
explain情況 走了(b a)的索引 但是只是走了部分沒有走完全,而且extra沒有檔案排序
分析 大概可知執行順序 是先進行了索引排序 範圍取值 然後導致聯合索引中斷,去掉order by發現就走了(a,b)聯合索引,這是典型的由於排序導致的索引的錯誤選擇
解決方法 改寫sql select * from (select * from table where a in () and b >'') t order by t,b desc 將排序放在外迴圈即可
案例8select injer join injer join injer join group by order by limit 10 ,20
分析 根據expain分析 掃瞄行數只有2千行,但是執行用了2min,既然不能依賴explain 就定位**出了問題.
1 先去掉 group by order by 執行 結果速度一樣,證明不是分組排序導致
2 先執行第乙個injer join 記錄時常
3 再 加入乙個injer join 再記錄時常
最後發現 每加乙個injer join表 執行時間就耗時增加一倍,這樣問題就好定位了
解決方法 將第乙個injer join改成 in () 速度比之前快了很多,
總結 1 減少join的次數,用in代替 2 當explain無法分析出原因的時候 要手動進行排查定位
mysql 查詢優化案例計算
有表takeout goods,id是自增主鍵,shop id是普通b 樹索引,其他欄位本案例用不著 語句如下 語句1 explain select from takeout goods where shop id 7691005 對於這條語句,查詢優化器有兩種走法,一種是去主鍵索引走全表掃瞄,另一...
Mysql查詢語句優化之索引優化案例
sql優化說到底還是索引的優化,建立索引並使之生效.單錶優化 create table student id int 11 not null auto increment,stuname varchar 60 default null,age int 11 default null,varchar ...
mysql優化案例
1 使用join還是子查詢 select from employee left join test on test.id employee.id select employee.select id from test where test.id employee.id t from employee...