最近因爲公司事情多,忙於項目發佈,因此很久都沒有更新,如今項目上線了能夠稍微有空繼續整理了。
今天要說的是MySQL中的索引問題,這也是在發佈項目時由於有一條SQL沒有使用索引直接致使該模塊整個不能使用,發佈失敗!也是藉此機會將本身所瞭解和學習到的索引的相關知識作一個整理。
衆所周知,索引不是一句兩句,也不是一篇兩篇能解釋完盡的,因此這裏會分紅好幾篇來說解,而且後續會持續的更新。若是文章中有不正確的地方但願你們能指正,互相討論,共同進步。
這次廢話略多,接下來進入正文,話很少說先上圖。算法
索引:是對數據庫表中一列或多列的值進行排序的一種存儲結構,使用索引可快速訪問數據庫表中的特定信息
這是比較官方的一種解釋,其做用至關於圖書的目錄,能夠根據目錄中的頁碼快速找到所需的內容,因此簡而言之索引就是用來提升查詢性能的一種手段。數據庫
優勢:數組
缺點:數據結構
適用於索引的數據結構主要有哈希表,有序數組,樹,這裏簡單介紹常見的三種。性能
哈希表結構學習
哈希表結構就是Key-Value的鍵值對的方式,如此查詢的時間複雜度只有O(1),查詢速度比較快,可是這種結構不適用於範圍類型的查詢。
哈希表的底層使用的是數組+鏈表,經過hash算法對key進行計算獲得數組中的槽位,而後將value存於該槽位,若是已經有數據了,則以鏈表的方式日後排列。自適應哈希索引使用的就是這種結構。通常這種結構在NoSQL引擎中使用比較多。優化
有序數組指針
使用有序數組來作索引在等值查詢和範圍查詢中具備很高的性能,可是在進行插入和刪除時就比較麻煩,因此只適合用於靜態存儲引擎。cdn
B+Tree B+Tree是在搜索樹的基礎上發展過來的,其特色就是扇出比較高,對於千萬級數據量的搜索只要2-4次I/O。須要注意的是B+Tree的數據所有放在葉子節點。在咱們經常使用的InnoDB引擎中默認的索引都是這種數據結構實現的。blog
在InnoDB中其實只有兩種類型的索引聚簇索引和輔助索引(非聚簇索引)。這兩種索引都是使用的B+Tree來實現的。下面詳細的介紹一下。
咱們知道在InnoDB中,每一張表都會有主鍵,若是沒有顯示指明主鍵,那麼會使用惟一約束字段做爲主鍵,若是也沒有惟一約束,那麼InnoDB會使用一個6個字節的指針row_id做爲這個表中的主鍵。
而聚簇索引就是創建在主鍵上面的索引,所以也稱爲主鍵索引,同時葉子節點中存放的即爲整個表的行記錄數據,所以也將聚簇索引的葉子節點稱爲數據頁。
通常狀況下,有多個索引時優化器會優先使用聚簇索引來進行查詢。
對於輔助索引,也稱爲非聚簇索引,在輔助索引的葉子節點中並不包含行記錄的所有數據,葉子節點保存的是相應行數據的聚簇索引鍵。一個表上面只能有一個聚簇索引,可是能夠有多個輔助索引。
當使用輔助索引來查詢時會先拿到主鍵索引的主鍵,而後再經過主鍵索引獲得完整的行記錄,回到主鍵索引的這個過程稱爲回表。
全部的系統都有一個最小的存儲單元,Windows中的文件系統是4kB,在InnoDb引擎中最小的存儲單元是16KB,這個在單元在InnoDB中能夠稱爲一個「頁」(Page)。
前面咱們說過在InnoDB中索引的數據結構是B+Tree,那麼B+Tree是個什麼樣的結構呢?
B+Tree是目前關係型數據庫系統中最爲經常使用和最爲有效的索引,其相似於二叉樹(B+Tree不是二叉樹),能夠根據鍵值(key-value)快速找到數據。
B+Tree樹索引並不能找到一個給定鍵值的具體行,它只能找到被查找的數據行所在的頁,而後把頁讀入內存,再使用二分法獲得要查找的數據。
這裏對B+Tree作個簡單的定義:它是一種平衡查找樹,在B+Tree中,全部記錄節點都是按鍵值的大小順序存放在同一層的葉子節點上,由各個葉子節點指針進行鏈接。以下圖是一個簡單的B+Tree結構圖,其高度爲2,每頁能夠存放4個數據頁,扇出爲4。
在向樹中插入或者刪除時,爲了保持整棵樹的平衡,可能須要大量的拆分頁操做,所以B+Tree會有自旋功能,避免沒必要要的拆分工做。上面說了InnoDB使用頁來管理存儲,因此全部的表數據都是存放在B+Tree的葉子節點,非葉子節點存放索引值和指針。
以前說過MySQL經過索引只須要2-4次的I/O就能找到對應的數據,這是爲啥呢?咱們接下來能夠簡單的分析一下:
假設一行記錄1KB=1024B大小,那麼主鍵ID爲BIGINT類型就是8個字節大小(8B),而指針是6B,那麼一個16KB大小的頁能夠存儲16 * 1024/(8+6) = 1170 個指針,那麼高度爲2的B+Tree大概能夠有1170 * 16 =18720條記錄,高度爲3的B+Tree能夠有1170 * 1170 * 16 = 21902400條記錄,因此千萬級的表經過索引只要2-4次的I/O就能將數據查詢出來。
從上面的推理能夠得出主鍵長度越小,那麼效率就越高。 因此從性能和存儲空間方面考量,自增主鍵每每是更合理的選擇。