mysql學習(2)索引的本質

問題:SQL查詢慢怎麼辦?

優化手段,加索引。mysql

索引是幫助MYSQL高效的獲取數據的排好序數據結構。sql

問題:索引結構爲何使用Btree而不使用二叉樹,紅黑樹或者HASH結構?

二叉樹的特性,右邊子節點的值大於父節點,且左邊子節點的值小於父節點數據庫

二叉樹:使用二叉樹來作索引的數據結構,當索引值遞增的時候,二叉樹也會不斷地增長右子節點 ,那麼在查找索引的時候,所作的IO操做,等同於沒有索引逐行查找數據的IO操做。數據結構

紅黑樹:平衡二叉樹。隨着數據量增大,樹的高度也會變高。2的N次方=數量量(假設100萬),那麼N至少也是50,那麼樹的高度也是50,若是數據在子葉節點上,那麼至少要通過50次的IO操做,才能找到數據。oracle

HASH:散列表結構,key不適合排序,並且數據是散列的分佈的,不利於IO讀寫。性能

BTree:一個節點上,橫向擴展。即一個節點上,能夠存儲多個元素(Degree),且每一個元素,均可以有子節點,叫作多叉樹。優化

  • 度(Degree)-節點的數據存儲個數
  • 葉節點具備相同深度
  • 葉節點的指針爲空
  • 節點中的數據KEY從左至右遞增排列

    以5階B樹舉例ui

B+Tree(Btree變種)spa

  • 非葉子節點不存儲data,只存儲key,能夠增大度(Degree)-節點的數據存儲個數
  • 葉子節點不存儲指針
  • 葉子節點增長了順序訪問指針,提升區間訪問的性能

以5階B+樹舉例指針

問題:Btree和B+Tree的區別?

  • Btree每一個節點,都包含了key和data,而B+tree只有葉子節點保存了key和data,其餘節點,只保存了key,方便增大度的個數
  • B+tree的葉子節點之間, 增長了指針,提升了查詢區間的性能,不須要像Btree同樣每次都從根節點開始查找
  • Btree中,父節點和葉子節點,關鍵字的字段值不會冗餘,而B+tree會冗餘的存儲關鍵的索引值,即父節點和葉子結點都存在相同的關鍵值

MyISAM索引實現(非彙集)

MyISAM索引文件和數據文件是分離的。它是針對建表的,而不是針對數據庫的,既同一個數據庫能夠多種類型的表,myISAM和innoDB。

在mysql的文件件中,會發現一個表有三個文件:

  • test_table_myisam.frm // 存儲表的結構,表的定義
  • test_table_myisam.MYD // 存儲表的數據
  • test_table_myisam.MYI // 存儲表的索引文件

myisam存儲引擎是非彙集索引,因此在MYI的文件中,以B+tree的數據結構存儲了表的索引信息,而索引內容中的data,是指向數據的在MYD文件中的地址。

在myisam存儲引擎中,主鍵索引使用了B+tree,而輔助索引,非主鍵索引,也一樣根據字段的值,使用了B+tree結構來存儲。

innoDB索引實現(彙集)

  • 表數據文件自己就是按B+Tree組織的一個索引結構文件

   

  • 彙集索引 定義:葉節點包含了完整的數據記錄
  • 爲何innoDB表必須有主鍵,而且推薦使用整形的自增主鍵?
  • 爲何非主鍵索引結構葉子節點存儲的是主鍵值?(一致性和節省存儲空間)

在mysql的文件件中,會發現一個表有兩個文件:

  • test_table_myisam.frm  // 存儲表的結構,表的定義
  • test_table_myisam.ibd  // 存儲表的索引+數據

在innoDB存儲引擎中,輔助索引、非主鍵索引都不是彙集索引。

問題:爲何B+tree比Btree快?

樹的高度h,影響了查找效率,由於從根節點開始,每次查找下一個節點,均可能須要一次IO讀寫。因此增長非葉子節點的度,能夠有效提升查詢效率。而CPU從磁盤上讀取數據到內存中,最小單元是頁,一頁讀取的最小數據是4KB,而CPU一次IO,讀取的數據是一頁的整數倍,且最大值也有限制。而mysql在底層,設置的大小是16KB。因此B+TREE要把數據放在葉子節點,因此非葉子幾點,就能夠增長更多的節點數。而Btree節點和數據是保存在一塊兒的,因此非葉節點的節點數,要比B+tree少,樹的高度就比B+tree高。

問題:爲何MYSQL頁文件默認的配置是16KB?

咱們假設一行的數據是1K,那咱們一頁的數據,就能存儲16行數據,也就是一個葉節點能夠存儲16條記錄;再來看非葉節點,假設ID是bigint類型,那麼長度爲8B,指針大小在InnoDB源碼中爲64(6B),一共就是14B,那麼一頁裏面就能夠存儲16K/14=1170個(主鍵+指針)

那麼一顆高度爲2的B+樹能存儲的數據爲:1170*16=18720條,一顆高度爲3的B+樹能夠存儲1170*1170*16=21902400(千萬條)

緣由就是16KB就足夠應對千萬條表記錄了。

問題:爲何innoDB表必須有主鍵,而且推薦使用整形的自增主鍵?

         使用innoBD存儲引擎時,要創建主鍵索引,若是咱們沒有主動建立索引,那麼innoDB會自動幫咱們創建主鍵索引。innoDB會在咱們建立的表裏找一列惟一的,能夠表明主鍵的字段來建立主鍵索引,若是沒有這樣的字段,innoDB會默認加一列字段,來建立主鍵索引。有點相似oracle中的rowId。爲何要推薦整形並且自增的字段當作主鍵?爲何建議使用整形類型,由於若是使用uuid做爲主鍵索引,uuid類型比整數類型大,爲了方便IO操做一次讀取4個頁的數據(mysql默認16KB,一頁是4KB),意味索引的非葉子節點上的關鍵字要比使用整數類型的關鍵字數量小,那麼B+tree的高度就可能增長,那麼讀取葉子節點上的數據的IO操做次數就增長了。那麼查找的效率就低了。爲何要自增,由於當新紀錄插入時,主鍵自增的話,在B+tree中插入節點比較方便,而使用uuid爲主鍵,新紀錄的uuid不必定比前面的uuid大,可能會將新紀錄插在靠前面的葉子節點中,葉子節點滿了,會取中間的關鍵字向上存放到父節點中,可能會形成樹的分裂,微觀上性能就比自增的差。

相關文章
相關標籤/搜索