索引原理
從底層看,如何選擇表的主鍵忘嫉?
推薦使用自增ID,因為有序這樣使每次新插入的對象都在樹的子節(jié)點的最右側案腺,如果用例如UUID之類的庆冕,沒有物理連續(xù)性,在樹上無序的插入劈榨,分裂耗費資源访递,另外這種id很長,空間占有也比int大同辣。
執(zhí)行計劃
解釋幾個比較重要的參數
Type:
sql查詢優(yōu)化中一個很重要的指標拷姿,結果值從好到壞依次是:
system> const > eq_ref > ref > fulltext > ref_or_null > index_merge> unique_subquery > index_subquery > range > index > ALL
key:
實際使用的索引
Key_len:
所使用的索引的長度,越短越好旱函。為什么响巢?看索引樹,索引長了占空間棒妨。
Rows:
找到所需要的記錄需要讀取的行數踪古,當然也越小越好
Extra:
注意兩個:1,using filesort文件排序券腔,無法用索引完成排序操作伏穆,需要優(yōu)化
2.using
temporary 用到了臨時表,會做數據的拷貝很耗費資源
聯(lián)合索引
首先拿個sql分析一下執(zhí)行計劃纷纫,發(fā)現沒有走索引枕扫,
然后看一下該表的索引結構
僅僅有新建表的時候自動建的主鍵索引,所以應該建索引,怎么建涛酗?先分別建铡原,
再看看執(zhí)行計劃呢?
只使用了一個索引商叹,
結論:這種情況下mysql只會選擇一個索引燕刻,所以考慮聯(lián)合索引
接下來刪除這三個索引,建一個聯(lián)合索引
再看執(zhí)行計劃
這樣效率就很明顯了剖笙。探索一下聯(lián)合索引的最左原則
結論:a,b,c可以順序無所謂卵洗,mysql會替你優(yōu)化(具體情況具體分析,不是一定的)
a
a,b
a,c
b,c
結論:a,b,c這樣的聯(lián)合索引只要有a就能走索引
Like ‘%***’
Like ‘***%’
結論:Like ‘%***’不能命中索引。
補充一點:聯(lián)合索引有的場景下可以解決排序的問題
結合測試結果过蹂,針對篩選條件很多的列表頁十绑,怎么做索引優(yōu)化呢?
分析一下剛才的結論
第一:where條件后只能有一個索引被用到
第二:聯(lián)合索引只要有最左邊的字段就能走索引
第三:聯(lián)合索引可以不要求where條件后面的字段有序(cba,ca)
現在再來設計一下:
最好找一個默認一定會查詢的字段作為聯(lián)合索引的a(最左)酷勺,這樣用戶不選擇條件又或者是選擇查詢條件本橙,都會走聯(lián)合索引。默認一定會查詢的字段怎么找脆诉?例如用戶的角色去篩選等等甚亭,這個就得具體業(yè)務具體分析了
覆蓋索引
既然說到了聯(lián)合索引那就順帶說一下覆蓋索引。啥叫覆蓋索引击胜?就是你select的字段都是聯(lián)合索引中的字段亏狰,比如有聯(lián)合索引abc,那么”select a,b,c from table where a=’*’ and b =’*’ and c=’*’”這樣的就是覆蓋索引偶摔。
覆蓋索引為什么效率很高暇唾?
從索引原理的索引樹上來看,可以直接在索引文件的索引樹上就能夠取到所有需要查詢的字段辰斋,那直接通過遍歷索引取得了數據策州,不需要回表,減少了io操作宫仗,性能自然就提高了抽活。
鎖
Myisam:表鎖(并發(fā)度不夠)
Innodb:表鎖,行鎖
Sql優(yōu)化為什么要說說鎖锰什?首先即使是行鎖下硕,要鎖定某一行,獲取鎖和釋放鎖的過程也是復雜的汁胆,耗資源的梭姓,所以盡量別讓一個事物鎖住一大片。另外如果程序員寫代碼不規(guī)范也可能產生死鎖嫩码。
怎么產生死鎖誉尖?
首先表鎖肯定是不會產生死鎖了,鎖住了整張表怎么還能產生死鎖呢铸题。但是如果是行鎖铡恕,舉個例子:
T1鎖住table1的id=1行,等待table2的id=11行丢间,T2鎖table2的id=11,待table1的id=1行探熔,相互等待
所以在系統(tǒng)業(yè)務繁忙的時候別去做大批量的update,會導致鎖表烘挫,從而阻塞掉業(yè)務诀艰,導致超時。
JION
Join的原理是什么?
怎么看Join buffer的大衅渎ⅰ苛蒲?
Showvariables like ‘join_%’
Order by
盡量去命中索引,為什么绿满?
用到了文件排序
Using filesort沒有了臂外,因為索引已經替我們做了排序(葉子節(jié)點從左到右相互指向)
那么在沒有索引的情況下,order by的排序是怎么樣做的呢喇颁?
當你的buffer夠大時寄月,mysql會選擇第二種排序方式,否則第一種无牵,顯然一次IO的效率好于兩次,所以一定要什么字段就拿什么字段厂抖,千萬別select * ,另外必要時可以增大buffer的大小
Group by
基于order by,先排序再分組
可以看到茎毁,也用到了索引,所以優(yōu)化方式和order by一樣
Distinct
基于group by
Limit
例子是針對自增id的
要查第7忱辅,8行會拿到我們表的9行
這樣呢就只有3行
七蜘!=
用到了索引
。墙懂。橡卤。。還有很多损搬,建議大家自己去嘗試碧库,別死記硬背,理解原理巧勤,另外數據庫版本不同是否走索引的結果也不一定一樣
寫在最后
建議慢sql首先考慮人為因素嵌灰,需求是否合理,表結構是否合理颅悉,sql設計是否合理沽瞭,這件事情到底適不適合或者說應該還是不應該讓關系型數據庫去做。