一、MySql索引的介紹
1、定義
索引是幫助MySQL高效獲取數據的數據結構,其本質是數據結構。
簡單的可理解爲一句話:排好序的快速查找數據結構,用於排序和快速查找。
一般來索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲在磁盤上。
2、常見疑問
爲啥都說,索引不能建立在頻繁更新的字段上?
原因是:因爲你在平凡更新數據的時候,索引也同時會去維護操作數據的指向,這樣我們在頻繁更新數據的時候就會慢。
3、索引的優勢和劣勢
優勢:
- 提高數據檢索的效率,降低數據庫的IO成本。
- 通過索引列對是數據進行排序,降低數據排序的成本,降低了CPU的消耗。
劣勢:
- 實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,所以索引列也是要佔用空間的 。
- 雖然大大提高了查詢的速度,同時也會降低更新表的速度。
二、索引的分類
單值索引:即一個索引只包含一個單列,一個表可以有多個單列索引(一般不能建立5個索引)。
唯一索引:索引列的值必須唯一,但允許爲空值。
複合索引:即一個索引包含多列。
三、索引的數據結構
- 二叉樹
- 紅黑樹
- Hash表
- B-Tree
1、二叉樹數據結構的索引
二叉樹算法索引數據結構普分佈圖
如果我們要查select * from t where col2=89這行數據情況:
對應圖的右邊就有個二叉樹的算法,結構就是一個key,value的存儲結構,key就是我們的索引,value就是索引字段所在行的那個磁盤地址文件指針。
根據二叉樹的特點,右邊的子節點是大於父節點的,左邊小於父節點,分析:
如果col2數據是依次遞增的情況,那按照我們的二叉樹算法的特性,就變成了單邊增長的情況了,最終就會變成一個鏈表的形式。
出現鏈表的形式就會像上圖, 這樣我如果要查col2=0006,會查6次,很顯然不符合我的要求。
2、紅黑樹數據結構的索引
測驗分析圖:
根據圖上的編號得出:
其實紅黑樹也是一種二叉樹,它叫做二叉平衡樹,如果單邊增長的太多,就會自動去平衡,隨着數據量的增大,會不停的去移動平衡。
對第一種二叉算法的優化:
在使用紅黑樹數據結構後相比第一種的二叉樹查找要優一些,很明顯,查col2=0006只用了3次。
劣勢:
假如在我們實際的項目中,有百萬級的數據,通過測驗分析圖和二叉平衡樹的特點,會出現這棵樹的高度越來越大,這樣我們查最底下的數據,這樣從上往下查,又會查很多次,隨着數據量的增大,紅黑樹數據結構算法不符合實際的情況。
2、B-Tree和B+Tree數據結構的索引
問題?
在紅黑樹的基礎上再次優化,優化的點很顯然就是控制我們樹的高度問題,讓這棵樹只有3-5層的高度就能存放千萬級的數據問題?
方案設想:
讓每個節點存放更多的索引元素,讓樹橫向發展,控制樹的高度,這樣其實就是我們B-Tree結構。
B-Tree分佈圖:
規則:
mysql給我們的一個節點設置成16kb,在運行的時候先將一個節點放入到我們的內存當中,
疑問?
那千萬級的數據完全可以放在一個節點呀,這樣樹的高度是1,這樣查不是很快嗎?問題是如果是千萬級的數據都放在一個節點,這樣一進來就將這千萬級的數據打入到內存,很明顯這樣會消耗我們的很大內存,顯然是不合適的。
B+Tree分佈圖:
B+Tree特點:
- B+Tree是一顆多叉平衡樹,其葉子節點也是一個二叉樹。
- 與B-Tree的區別在於,B+Tree多了非葉子節點,從上圖可以看出,第一個和第二個節點存放都是索引元素,並沒有存放data值,葉子節點存放了所有的索引元素,而且每個節點還多了個指向箭頭。
爲啥要這樣分佈呢?爲啥會有非葉子階段?
原因是:一個節點存放的索引是有大小限制的,如mysql默認設置一個節點爲16kb,如果非葉子節點不存放我們的data數據指針,這樣我們一個節點就可以存放更多的索引元素。
四、根據不同存儲引擎來分析B+Tree的索引
1、MyISAM存儲引擎索引實現
解析圖
查看數據庫的data文件可以看出MyISAM表在我們的磁盤上存放了三個文件分別是:
.frm文件:存放表結構定義的數據。
.MYD文件:存放數據的文件。
.MYI文件:存放索引的文件。
索引查找過程:
比如我們現在要查找上圖中的col2=89的元素,那麼執行過程就是:
通過B+Tree依次比對查找,查找到一個節點就放到我們內存當中,最終查找了索引89這行索引元素也就是key,就可以找到這個key對應value,這個vlue就是當前索引所在那一行的磁盤文件地址指針,然後這個指針就會去我們的.MYD文件快速的定位到需要查找的這一行。
2、InnoDB存儲引擎索引實現
解析圖
查看數據庫的data文件可以看出InnoDB表在我們的磁盤上存放了二個文件分別是:
.frm文件:存放表結構定義的數據。
.ibd文件:存放數據和索引數據文件,將其數據文件和索引數據文件合併到一個文件了。
本身就利用了b+tree的結構存儲模式。
特點:
- 與MyISAM分析圖對比明顯看出葉子節點存儲實施有所不同的,b+tree葉子節點不僅存放了索引的元素還存儲了具體的數據。
- 它是個聚集索引,而MyISAM是一個非聚集索引,這兩者的定義的就是來源於我們的存儲方式的不同,下面我們來分析下:
InnoDB存儲引擎葉子節點把索引和數據都存放在一起了,也就是全部存放在.ibd文件了,不需要像MyISAM存儲引擎那 樣,數據和索引分開單獨文件存儲,也InnoDB存儲引擎不需要去找myi文件了, 很顯然查找的效率比MyISAM存儲引 擎要快。
InnoDB表爲啥必須要有主鍵?並且推薦使用整形的自增主鍵?
mysql設計如此必須要有主鍵?
如果你沒有建立主鍵,mysql後臺會給你默認選擇一個字段加一個主鍵,因爲它必須要主鍵,才能組織數據。
爲啥整形的主鍵?
如果用字符型的uuid的方式去設置主鍵的話,那比較起來就麻煩了,字符串要轉成我們的ACSII碼然後在進行比較很顯然比我們的整形直接拿來比較效率要低,佔用的空間上整形也比字符串要少,節約空間。
爲啥要自增?
b+tree索引的特性是從左到右依次遞增的過程,在我們葉子節點有個指針,這樣順序指定會加快我們的查找效率。
如果不是遞增去存放的,實例情況:1,2,3,4,5,6,7,9,10。這裏缺少了一個8,如果我在10後面再去插入8,這時候我們的樹就會分裂,樹做了自動平衡,這些都是有性能開銷的,會做大量的運算。
五、哪些情況下適合建立索引?哪些情況下不適合建立索引
哪些情況下適合建立索引?
- 主鍵自動建立唯一索引。
- 頻繁作爲查詢條件的字段應該創建索引。
- 查詢中與其他表關聯的字段,外鍵關係建立索引。
- 頻繁更新的字段不適合建立索引。
- where條件裏面用不到的字段不創建索引。
- 單鍵/組合索引選擇問題(在高併發下傾向選擇組合索引)。
- 查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序的速度。
- 查詢中統計或者分組的字段需要創建索引,(因爲分組會設計到排序的問題)。
哪些情況下不適合建立索引?
- 表記錄太少。
- 經常增刪改的表:提高了查詢的速度,同時卻降低了更新表的速度,因爲MySQL在更新表數據的同時還要更新保存下索引文件。
- 數據重複且分佈平均的表字段,應該只爲最經常查詢和最經常排序的數據列建立索引。
- 注意如果某個數據列包含許多重複的內容,爲他建立索引就沒有太大的實際效果。(如:性別字段)
導致索引優化的點