淺談MySQL的索引(1)

??????索引,不光是我們再工作中時常用到的一個名詞,在面試的時候也是逢考必面的知識點,索引可以讓我們的速度提升千百倍效率,也可以讓我們本來運行很ok的sql變的不那么“和諧”,接下來我們就聊聊索引。


一、什么是索引


??? MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數據的數據結構。

我們可以簡單理解為:快速查找排好序的一種數據結構。

或者理解為一本書的目錄,個人認為重點是“有序”。


  • 索引的本質就是數據庫中字段值的復制,該字段稱為索引的關鍵字;

  • 索引也是一張表,記錄保存了主鍵與索引字段,并指向了實際表數據;

  • 索引往往通過復雜的數據結構(雙向鏈表、hash、BTree/B+Tree、)實現;


  • MyISAM存儲引擎的表支持主索引,InnoDB存儲引擎的表支持聚簇索引(主索引)與非聚簇索引(輔助索引)索引優化使用。


    二、主流索引查找算法


  • 線性查找,是一個鏈表,要搜索的話,需要從第一個往后一個個找

  • 二分查找,是線性查找的升級,也就是說二分查找是可以用線性查找的數據接口,但是算法不一樣

  • 二叉樹查找,進一步提高性能,引入了二叉樹

  • 平衡二叉樹,二叉樹因為有平衡的問題,又進一步出現了平衡二叉樹

  • B樹,在平衡二叉樹之后又發現了一個問題,之前的數據結構每一個節點都是一個行數據,這樣的話對于磁盤的利用率是有問題的,因為我的數據要最終落到磁盤上,以一個節點為單位去讀取磁盤效率是很低的

  • B+樹,B樹效率也有問題,出現了B+樹,可以理解B+樹是B樹和線性的結合


  • 二、索引 的分類

  • 從索引存儲結構劃分:B Tree索引、Hash索引、FULLTEXT全文索引以及R Tree索引

  • 從應用層次劃分:普通索引、唯一索引、主鍵索引、復合索引

  • 從鍵值劃分:主鍵、輔助

  • 從數據存儲以及索引邏輯關系劃分:聚集索引、非聚集索引

  • 而Mysql索引主要有兩種結構:B+Tree索引和Hash索引。我們平常所說的索引,如果沒有特別指明,一般都是指B樹結構組織的索引(B+Tree索引)。


    接下來我們就一一介紹一下各個索引名詞:


    2.1、BTree 索引

    ????????BTree? 全稱?Balanced Tree,是一種很普遍的數據庫索引結構,oracle默認的索引類型。

    ????????其特點是定位高效、利用率高、自我平衡,特別適用于高基數字段,定位單條或小范圍數據非常高效。理論上,使用Btree在億條數據與100條數據中定位記錄的花銷相同。


    演算如下:
    讀取root節點,判斷82大于在0-120之間,走左邊分支。
    讀取左邊branch節點,判斷82大于80且小于等于120,走右邊分支。
    讀取右邊leaf節點,在該節點中找到數據82及對應的rowid
    使用rowid去物理表中讀取記錄數據塊(如果是count或者只select rowid,則最后一次讀取不需要)


    ????而由于Btree索引對結構的利用率很高,定位高效。當1千萬條數據時,Btree索引也是三層結構(依稀記得億級數據才是3層與4層的分水嶺)。定位記錄仍只需要三次I/O,這便是開頭所說的,100條數據和1千萬條數據的定位,在btree索引中的花銷是一樣的。


    Btree索引的自我平衡(平衡擴張)借用下面幾張圖進行說明:


    ?????新建一個索引,索引上只會有一個leaf節點,取名為Node A,不斷的向這個leaf節點中插入數據后,直到這個節點滿;


    ??????當Node A滿之后,我們再向表中插入一條記錄,此時索引就需要做拆分處理:會新分配兩個數據塊NodeB & C,如果新插入的值,大于當前最大值,則將Node A中的值全部插入Node B中,將新插入的值放到Node C中;否則按照5-5比例,將已有數據分別插入到NodeB與C中;


    無論采用哪種分割方式,之前的leaf節點A,將變成一個root節點,保存兩個范圍條目,指向B與C,結構如下圖:


    當Node C滿之后,此時 Node A仍有空余空間存放條目,所以不需要再拆分,而只是新分配一個數據塊Node D,將在Node A中創建指定到Node D的條目:


    如果當根節點Node A也滿了,則需要進一步拆分:新建Node E&F&G,將Node A中范圍條目拆分到E&F兩個節點中,并建立E&F到BCD節點的關聯,向Node G插入索引值。此時E&F為branch節點,G為leaf節點,A為Root節點:


    在整個擴張過程中,Btree自身總能保持平衡,Leaf節點的深度能一直保持一致。

    參考文章:http://zsuil.com/?p=1184


    2.2、B+Tree索引

    MySQL數據庫索引采用的是B+Tree結構,在B-Tree結構上做了優化改造,其特點:

  • 只有葉子節點包含索引和數據

  • 非葉子節點只存儲索引值

  • 葉子節點用指針連接,提高區間訪問性能

  • 對比B樹來說,B+樹范圍查找時,只需要定位倆個節點的索引值,然后利用葉子節點指針進行遍歷即可,而B樹需要遍歷范圍內所有的節點數據,倆相對比,B+樹效率更高




  • 2.3、Hash 索引

    ????Hash索引是基于Hash表實現,只有查詢條件精確匹配Hash索引中的所有列時,才能夠使用到Hash索引。也就是說,Hash索引只能用在等值查詢,那么范圍和模糊查詢就不可以了;存儲結構如下圖:


    ????對于Hash索引中的所有列,存儲引擎都會為每一行計算一個Hash碼,Hash索引中儲存的就是Hash碼。

    ????Hash索引表中保存每一個Hash索引所代表的數據行的指針,由于Hash索引本身只存儲Hash碼,所以Hash索引結構比較緊湊,那么查詢速度比較快。


    2.2、FULLTEXT全文索引

    全文索引,通過建立倒排索引,可以極大的提升檢索效率,解決判斷字段是否包含的問題.?


    例如: 有title字段,需要查詢所有包含 "政府"的記錄. 需要 like "%政府%"方式查詢,查詢速度慢,當查詢包含"政府" OR "中國"的需要是,sql難以簡單滿足.全文索引就可以實現這個功能.


    舊版的MySQL的全文索引只能用在MyISAM表格的char、varchar和text的字段上。?

    不過新版的MySQL5.6.24上InnoDB引擎也加入了全文索引,所以具體信息要隨時關注官網,

    --?方式1、創建表的同時創建全文索引CREATE?TABLE?article?(????id?INT?AUTO_INCREMENT?NOT?NULL?PRIMARY?KEY,????title?VARCHAR(200),?????????body?TEXT,?????????FULLTEXT(title,?body)?)?TYPE=MYISAM;?--?方式2.通過?alter?table?的方式來添加ALTER?TABLE?`student`?ADD?FULLTEXT?INDEX?ft_stu_name??(`name`)?;??--?ft_stu_name是索引名,可以隨便起??--?或者:ALTER?TABLE?`student`?ADD?FULLTEXT?ft_stu_name??(`name`);--?方式3.?直接通過create?index的方式CREATE?FULLTEXT?INDEX?ft_email_name?ON?`student`?(`name`);??--?也可以在創建索引的時候指定索引的長度:CREATE?FULLTEXT?INDEX?ft_email_name?ON?`student`?(`name`(20));

    使用全文索引

    ?使用全文索引的格式:??MATCH?(columnName)?AGAINST?('string');?eg:?????????SELECT?*?FROM?`student`?WHERE?MATCH(`name`)?AGAINST('聰');????????當查詢多列數據時:?????????建議在此多列數據上創建一個聯合的全文索引,否則使用不了索引的。???????SELECT?*?FROM?`student`?WHERE?MATCH(`name`,`address`)?AGAINST('聰?廣東');


    不知不覺寫到這已經2k多字了,本期我們就寫到這里,下期我們繼續

    探討索引。
    …………………………………分割線……………………………

    不積跬步,無以至千里;不積小流,無以成江海。

    我都墨跡這么半天了 ,你不點關注,不點贊,不收藏,還不轉發,你想干啥!!!!

    關注我,每天分享一些小知識點。分享自己的小心得,包含但不限于初、中、高級面試題呦!!!

    最后編輯于
    ?著作權歸作者所有,轉載或內容合作請聯系作者
    平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

    推薦閱讀更多精彩內容

    • 個人專題目錄[http://www.lxweimin.com/p/140e2a59db2c] 1. 性能下降SQL...
      Java及SpringBoot閱讀 1,303評論 0 4
    • 索引的分類 從存儲結構上來劃分: BTree索引(B-Tree或B+Tree索引),Hash索引,full-ind...
      double_hi閱讀 318評論 0 0
    • 先來看個問題 假設現在有100000條從0到10000且從大到小排列的整型數據,1條數據的大小假設(真的只是假設)...
      kindol閱讀 538評論 0 2
    • 說到索引,很多人都知道“索引是一個排序的列表,在這個列表中存儲著索引的值和包含這個值的數據所在行的物理地址,在數據...
      愛情小傻蛋閱讀 703評論 2 2
    • 一、MySQL中索引的語法 創建索引 在創建表的時候添加索引 在創建表以后添加索引 注意: 索引需要占用磁盤空間,...
      _大叔_閱讀 213評論 0 1