??????索引,不光是我們再工作中時常用到的一個名詞,在面試的時候也是逢考必面的知識點,索引可以讓我們的速度提升千百倍效率,也可以讓我們本來運行很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 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多字了,本期我們就寫到這里,下期我們繼續
探討索引。
…………………………………分割線……………………………
不積跬步,無以至千里;不積小流,無以成江海。
我都墨跡這么半天了 ,你不點關注,不點贊,不收藏,還不轉發,你想干啥!!!!
關注我,每天分享一些小知識點。分享自己的小心得,包含但不限于初、中、高級面試題呦!!!