mysql索引: 是一種幫助mysql高效的獲取數據的數據結構,這些數據結構以某種方式引用數據,這種結構就是索引。可簡單理解爲排好序的快速查找數據結構。若是要查「mysql」這個單詞,咱們確定須要定位到m字母,而後從下往下找到y字母,再找到剩下的sql。java
1.1:索引分類node
單值索引:一個索引包含1個列 create index idx_XX on table(f1) 一個表能夠建多個。 惟一索引: 索引列的值必須惟一,但容許有空值 create unique index idx_XX on table(f1) 複合索引: 一個索引包含多個列 如:create index idx_XX on table(f1,f2,..)mysql
1.2:索引結構程序員
BTree Hash索引 full-text全文索引:面試
1.3:什麼狀況創建索引算法
主鍵自動創建惟一索引 頻繁做爲查詢條件的字段因該建立索引 查詢中與其餘表關聯的字段,外鍵關係創建索引 頻繁更新的字段不適合創建索引 where條件裏用不到的字段不創建索引 單鍵/複合索引的選擇(高併發下傾向複合) 查詢中排序的字段因創建索引 查詢中統計或分組字段sql
1.4:什麼狀況建不創建索引數據庫
頻繁增刪改的表 表記錄太少 數據重複且分佈平均的表字段。(重複太多索引意義不大)編程
2.1:B+樹在數據庫索引中的應用數組
目前大部分數據庫系統及文件系統都採用B-Tree或其變種B+Tree做爲索引結構
1)在數據庫索引的應用
在數據庫索引的應用中,B+樹按照下列方式進行組織 :
① 葉結點的組織方式 。B+樹的查找鍵 是數據文件的主鍵 ,且索引是稠密的。也就是說 ,葉結點 中爲數據文件的第一個記錄設有一個鍵、指針對 ,該數據文件能夠按主鍵排序,也能夠不按主鍵排序 ;數據文件按主鍵排序,且 B +樹是稀疏索引 , 在葉結點中爲數據文件的每個塊設有一個鍵、指針對 ;數據文件不按鍵屬性排序 ,且該屬性是 B +樹 的查找鍵 , 葉結點中爲數據文件裏出現的每一個屬性K設有一個鍵 、 指針對 , 其中指針執行排序鍵值爲 K的 記錄中的第一個。
② 非葉結點 的組織方式。B+樹 中的非葉結點造成 了葉結點上的一個多級稀疏索引。 每一個非葉結點中至少有ceil( m/2 ) 個指針 , 至多有 m 個指針 。
2)B+樹索引的插入和刪除
①在向數據庫中插入新的數據時,同時也須要向數據庫索引中插入相應的索引鍵值 ,則須要向 B+樹 中插入新的鍵值。即上面咱們提到的B-樹插入算法。
②當從數據庫中刪除數據時,同時也須要從數據庫索引中刪除相應的索引鍵值 ,則須要從 B+樹 中刪 除該鍵值 。即B-樹刪除算法
2.2: 索引在數據庫中的做用
在數據庫系統的使用過程中,數據的查詢是使用最頻繁的一種數據操做。
最基本的查詢算法固然是順序查找(linear search),遍歷表而後逐行匹配行值是否等於待查找的關鍵字,其時間複雜度爲O(n)。但時間複雜度爲O(n)的算法規模小的表,負載輕的數據庫,也能有好的性能。 可是數據增大的時候,時間複雜度爲O(n)的算法顯然是糟糕的,性能就很快降低了。
好在計算機科學的發展提供了不少更優秀的查找算法,例如二分查找(binary search)、二叉樹查找(binary tree search)等。若是稍微分析一下會發現,每種查找算法都只能應用於特定的數據結構之上,例如二分查找要求被檢索數據有序,而二叉樹查找只能應用於二叉查找樹上,可是數據自己的組織結構不可能徹底知足各類數據結構(例如,理論上不可能同時將兩列都按順序進行組織),因此,在數據以外,數據庫系統還維護着知足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就能夠在這些數據結構上實現高級查找算法。這種數據結構,就是索引。
索引是對數據庫表 中一個或多個列的值進行排序的結構。與在表 中搜索全部的行相比,索引用指針 指向存儲在表中指定列的數據值,而後根據指定的次序排列這些指針,有助於更快地獲取信息。一般情 況下 ,只有當常常查詢索引列中的數據時 ,才須要在表上建立索引。索引將佔用磁盤空間,而且影響數 據更新的速度。可是在多數狀況下 ,索引所帶來的數據檢索速度優點大大超過它的不足之處。
2.3:爲何使用B-Tree(B+Tree)
1.文件很大,不可能所有存儲在內存中,故要存儲到磁盤上
2.索引的結構組織要儘可能減小查找過程當中磁盤I/O的存取次數(爲何使用B-/+Tree,還跟磁盤存取原理有關。)
3.局部性原理與磁盤預讀,預讀的長度通常爲頁(page)的整倍數,(在許多操做系統中,頁得大小一般爲4k)
4.數據庫系統巧妙利用了磁盤預讀原理,將一個節點的大小設爲等於一個頁,這樣每一個節點只須要一次I/O就能夠徹底載入,(因爲節點中有兩個數組,因此地址連續)。而紅黑樹這種結構,h明顯要深的多。因爲邏輯上很近的節點(父子)物理上可能很遠,沒法利用局部性
二叉查找樹進化品種的紅黑樹等數據結構也能夠用來實現索引,可是文件系統及數據庫系統廣泛採用B-/+Tree做爲索引結構。
通常來講,索引自己也很大,不可能所有存儲在內存中,所以索引每每以索引文件的形式存儲的磁盤上。這樣的話,索引查找過程當中就要產生磁盤I/O消耗,相對於內存存取,I/O存取的消耗要高几個數量級,因此評價一個數據結構做爲索引的優劣最重要的指標就是在查找過程當中磁盤I/O操做次數的漸進複雜度。換句話說,索引的結構組織要儘可能減小查找過程當中磁盤I/O的存取次數。爲何使用B-/+Tree,還跟磁盤存取原理有關。
局部性原理與磁盤預讀
因爲存儲介質的特性,磁盤自己存取就比主存慢不少,再加上機械運動耗費,磁盤的存取速度每每是主存的幾百分分之一,所以爲了提升效率,要儘可能減小磁盤I/O。爲了達到這個目的,磁盤每每不是嚴格按需讀取,而是每次都會預讀,即便只須要一個字節,磁盤也會從這個位置開始,順序向後讀取必定長度的數據放入內存。這樣作的理論依據是計算機科學中著名的局部性原理:
當一個數據被用到時,其附近的數據也一般會立刻被使用。
程序運行期間所須要的數據一般比較集中。
因爲磁盤順序讀取的效率很高(不須要尋道時間,只需不多的旋轉時間),所以對於具備局部性的程序來講,預讀能夠提升I/O效率。
預讀的長度通常爲頁(page)的整倍數。頁是計算機管理存儲器的邏輯塊,硬件及操做系統每每將主存和磁盤存儲區分割爲連續的大小相等的塊,每一個存儲塊稱爲一頁(在許多操做系統中,頁得大小一般爲4k),主存和磁盤以頁爲單位交換數據。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置並向後連續讀取一頁或幾頁載入內存中,而後異常返回,程序繼續運行。
咱們上面分析B-/+Tree檢索一次最多須要訪問節點:
數據庫系統巧妙利用了磁盤預讀原理,將一個節點的大小設爲等於一個頁,這樣每一個節點只須要一次I/O就能夠徹底載入。爲了達到這個目的,在實際實現B- Tree還須要使用以下技巧:
每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁裏,加之計算機存儲分配都是按頁對齊的,就實現了一個node只需一次I/O。
B-Tree中一次檢索最多須要h-1次I/O(根節點常駐內存),漸進複雜度爲O(h)=O(logmN)。通常實際應用中,m是很是大的數字,一般超過100,所以h很是小(一般不超過3)。
綜上所述,用B-Tree做爲索引結構效率是很是高的。
而紅黑樹這種結構,h明顯要深的多。因爲邏輯上很近的節點(父子)物理上可能很遠,沒法利用局部性,因此紅黑樹的I/O漸進複雜度也爲O(h),效率明顯比B-Tree差不少。
1)主鍵索引:
MyISAM引擎使用B+Tree做爲索引結構,葉節點的data域存放的是數據記錄的地址。下圖是MyISAM主鍵索引的原理圖:
這裏設表一共有三列,假設咱們以Col1爲主鍵,圖myisam1是一個MyISAM表的主索引(Primary key)示意。能夠看出MyISAM的索引文件僅僅保存數據記錄的地址。
2)輔助索引(Secondary key)
在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是惟一的,而輔助索引的key能夠重複。若是咱們在Col2上創建一個輔助索引,則此索引的結構以下圖所示:
一樣也是一顆B+Tree,data域保存數據記錄的地址。所以,MyISAM中索引檢索的算法爲首先按照B+Tree搜索算法搜索索引,若是指定的Key存在,則取出其data域的值,而後以data域的值爲地址,讀取相應數據記錄。
MyISAM的索引方式也叫作「非彙集」的,之因此這麼稱呼是爲了與InnoDB的彙集索引區分。
雖然InnoDB也使用B+Tree做爲索引結構,但具體實現方式卻與MyISAM大相徑庭。
第一個重大區別是InnoDB的數據文件自己就是索引文件。從上文知道,MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。而在InnoDB中,表數據文件自己就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,所以InnoDB表數據文件自己就是主索引。
上圖是InnoDB主索引(同時也是數據文件)的示意圖,能夠看到葉節點包含了完整的數據記錄。這種索引叫作彙集索引。由於InnoDB的數據文件自己要按主鍵彙集,因此InnoDB要求表必須有主鍵(MyISAM能夠沒有),若是沒有顯式指定,則MySQL系統會自動選擇一個能夠惟一標識數據記錄的列做爲主鍵,若是不存在這種列,則MySQL自動爲InnoDB表生成一個隱含字段做爲主鍵,這個字段長度爲6個字節,類型爲長整形。
第二個與MyISAM索引的不一樣是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的全部輔助索引都引用主鍵做爲data域。例如,下圖爲定義在Col3上的一個輔助索引:
這裏以英文字符的ASCII碼做爲比較準則。彙集索引這種實現方式使得按主鍵的搜索十分高效,可是輔助索引搜索須要檢索兩遍索引:首先檢索輔助索引得到主鍵,而後用主鍵到主索引中檢索得到記錄。
瞭解不一樣存儲引擎的索引實現方式對於正確使用和優化索引都很是有幫助,例如知道了InnoDB的索引實現後,就很容易明白爲何不建議使用過長的字段做爲主鍵,由於全部輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,用非單調的字段做爲主鍵在InnoDB中不是個好主意,由於InnoDB數據文件自己是一顆B+Tree,非單調的主鍵會形成在插入新記錄時數據文件爲了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增字段做爲主鍵則是一個很好的選擇。
以上是我總結出的Mysql索引底層數據結構剖析,但在此,我還想給你們一種學習方法,讓你們不僅僅在理論有所收穫,還能在工做實踐中收穫更多。我推薦的這種方法。
在此我向你們推薦一個交流學習羣:575745314 (加羣能夠學習程序員進階方法) 裏面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化這些成爲架構師必備的知識體系。還能領取免費的學習資源,目前受益良多
如下是程序員的進階方法:
1、源碼分析
2、分佈式架構
3、微服務
4、性能優化
5、團隊協做
六:電商實戰
七:併發編程