MySql索引分析

一、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,這時候我們的樹就會分裂,樹做了自動平衡,這些都是有性能開銷的,會做大量的運算。

五、哪些情況下適合建立索引?哪些情況下不適合建立索引

哪些情況下適合建立索引?

  1. 主鍵自動建立唯一索引。
  2. 頻繁作爲查詢條件的字段應該創建索引。
  3. 查詢中與其他表關聯的字段,外鍵關係建立索引。
  4. 頻繁更新的字段不適合建立索引。
  5. where條件裏面用不到的字段不創建索引。
  6. 單鍵/組合索引選擇問題(在高併發下傾向選擇組合索引)。
  7. 查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序的速度。
  8. 查詢中統計或者分組的字段需要創建索引,(因爲分組會設計到排序的問題)。

哪些情況下不適合建立索引?

  1. 表記錄太少。
  2. 經常增刪改的表:提高了查詢的速度,同時卻降低了更新表的速度,因爲MySQL在更新表數據的同時還要更新保存下索引文件。
  3. 數據重複且分佈平均的表字段,應該只爲最經常查詢和最經常排序的數據列建立索引。
  4. 注意如果某個數據列包含許多重複的內容,爲他建立索引就沒有太大的實際效果。(如:性別字段)

導致索引優化的點

mysql事物相關問題:https://blog.csdn.net/madongyu1259892936/article/details/98977500?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159054489119724811800708%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=159054489119724811800708&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~pc_rank_v3-2-98977500.first_rank_ecpm_v1_pc_rank_v3&utm_term=mysql%E4%BA%8B%E7%89%A9%E9%9D%A2%E8%AF%95%E9%A2%98

  https://www.bilibili.com/video/BV1aE41117sk?p=7

https://www.bilibili.com/video/BV1KW411u7vy?p=18

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章