繼上篇《讀懂MySQL執行計劃》後,在文章末尾,咱們談到了索引的概念,那麼,今天咱們就一塊兒來聊一聊MySQL索引。數據庫
百度百科是這樣描述的:服務器
索引是爲來加速對錶中數據行中的檢索而建立的一種分散的數據結果,時針對錶而創建的,它是由數據頁面之外的索引頁面組成,每一個索引頁中的行都含有邏輯指針,以便加速檢索物理數據微信
其實,索引的概念你們都很清楚,也知道索引可以提高查詢效率,但大部分童鞋在怎麼建索引,建在哪些字段上有如下常見誤解:架構
新建表時不須要建索引,後續才添加索引函數
where條件後的字段均建索引測試
簡單SQL不須要索引,聯合查詢才須要索引編碼
聯合索引的順序是where條件後字段的前後順序spa
對於區分度小的字段上也新建索引,如狀態,性別等字段等。.net
在說上述問題以前,咱們先來看看另外一個概念,就是區分度。設計
區分度: 指字段在數據庫中的不重複比
區分度在新建索引時有着很是重要的參考價值,在MySQL中,區分度的計算規則以下:
字段去重後的總數與全表總記錄數的商。
例如:
select count(distinct(name))/count(*) from t_base_user;
結果以下:
count(distinct(name))/count(*) |
---|
1.0000 |
其中區分度最大值爲1.000,最小爲0.0000,區分度的值越大,也就是數據不重複率越大,新建索引效果也越好,在主鍵以及惟一鍵上面的區分度是最高的,爲1.0000,在狀態,性別等字段上面的區分度值是最小的。 (這個就要看數據量了,若是隻有幾條數據,這時區分度還挺高的,若是數據量多,區分度基本爲0.0000。也就是在這些字段上添加索引後,效果也不佳的緣由。)
值得注意的是: 若是表中沒有任何記錄時,計算區分度的結果是爲空值,其餘狀況下,區分度值均分佈在0.0000-1.0000之間。
(一) : 區分度
我的強烈建議, 建索引時,必定要先計算該字段的區分度,緣由以下:
1. 單列索引
能夠查看該字段的區分度,根據區分度的大小,也能大概知道在該字段上的新建索引是否有效,以及效果如何。區分度越大,索引效果越明顯。
2.多列索引(聯合索引)
多列索引中其實還有一個字段的前後順序問題,通常是將區分度較高的放在前面,這樣聯合索引才更有效,例如:
select * from t_base_user where name="" and status=1;
像上述語句,若是建聯合索引的話,就應該是:
alter table t_base_user add index idx_name_status(name,status);
而不是:
alter table t_base_user add index idx_status_name(status,name);
(二) 最左前綴匹配原則
MySQL會一直向右匹配直到遇到範圍查詢(>、<、between、like)就中止匹配,好比
select * from t_base_user where type="10" and created_at<"2017-11-03" and status=1, (該語句僅做爲演示)
在上述語句中,status就不會走索引,由於遇到<時,MySQL已經中止匹配,此時走的索引爲:(type,created_at),其前後順序是能夠調整的,而走不到status索引,此時須要修改語句爲:
select * from t_base_user where type=10 and status=1 and created_at<"2017-11-03"
便可走status索引。
(三) 函數運算
不要在索引列上,進行函數運算,不然索引會失效。由於b+樹中存的都是數據表中的字段值,但進行檢索時,須要把全部元素都應用函數才能比較,顯然成本太大。
(四) 擴展優先
擴展優先,不要新建索引,儘可能在已有索引中修改。以下:
select * from t_base_user where name="andyqian" and email="andytohome"
在表t_base_user表中已經存在idx_name索引,若是須要加入idx_name_email的索引,應該是修改idx_name索引,而不是新建一個索引。
上面說了,如何新建索引,如今咱們就能夠來回答,在第一步中存在的誤解了。
誤解一: 新建表時不須要創建索引,後續才加索引
答: 一個好的數據表設計,在一開始就要考慮索引的建立,而不是等到後續出問題了,影響業務使用了,才新建索引來救場,並且後續建立索引的成本也相對高不少。(這就是給生產事故留下生根發芽的機會呀)
誤解二: where條件後的字段均建索引
答: 這個誤解比較常見,但where條件後的字段不須要所有創建索引,過多的索引,也會致使索引文件劇增,也還達不到指望中的效果。詳細請參考上述新建索引的小節。
誤解三: 簡單SQL不須要創建索引,聯合查詢採創建索引
答: 這個誤解就得好好說說了,如今互聯網公司特別是B/S架構下,業務邏輯均剝離在代碼邏輯層,到最後SQL層面,其實都是一些簡單的SQL,只有些許鏈接查詢,更多的仍是單表操做,(C/S架構中有不少在SQL層面的寫邏輯的),你說這些語句簡不簡單。
誤解四: 聯合索引的順序是where條件後字段的前後順序
答: 咱們剛纔說過,聯合索引的順序,是根據最左前綴原則,以及區分度來區分的,和where條件後字段的前後順序無關。
誤解五: 對於區分度較小的字段新建索引
答: 在區分度較小的字段上新建索引,基本無效,還會增長大量的索引文件,你說是否是得不償失。
上面介紹了MySQL索引的概念,新建索引時的一些技巧。這麼理論的東西,對於平時沒有使用或使用比較少的童鞋,此時對索引的重要性可能還沒那麼直觀,那麼,我就來講說我在索引上吃過的虧,踩過的坑!同時也是未建索引常見問題!
0. 致使慢查詢
這個問題但是未建索引的常客哦,(這裏也還有不少細節呢,如: 隱式類型轉換等等)
1. 致使服務超時
場景 :
在某次上線時,做爲服務提供者,提供服務給業務方使用。一開始覺得就提供一個簡單的服務,也已經測試完成,內心還在竊喜,今天總算能夠早早回家了!
描述 :
實際一上線,在生產環境中致使業務方請求調用時,並且每次請求均超時,數據也已落地,此時只能review代碼,最後發現生產中有個慢查詢致使,活活的花費了10多秒,這個語句有多簡單呢,你絕對想不到,就是一個簡單的單表where查詢。
你說這種緣由致使服務不可用,你說冤不冤,氣不氣!(這也是我爲何說,一個好的數據表設計,從一開始就要考慮新建索引了)。
2. 數據庫服務器CPU 100%
在查詢頻率比較高的SQL上,若是出現未建索引,致使慢查詢的話,那但是會致使數據庫服務器CPU 100%,影響但是整個系統哦。
小結
上面說了好幾類,因爲沒創建索引而致使的問題,輕則致使慢查詢,影響系統效率,重則,致使CPU 100%,影響整個系統的使用,看到這裏,你說索引重不重要?
上面簡單說了,索引是什麼?有什麼用,以及創建索引時的一些技巧,還着重說了,索引的重要性。那麼索引這麼重要,在平時編碼時如何避免呢? 如下是我我的的建議:
最後的最後: 你們辛苦一週,立刻就是週末了,祝你們週末愉快!
掃碼關注,一塊兒進步
我的博客: http://www.andyqian.com