第一節、深入淺出帶你認識Mysql索引

學習Mysql性能優化-索引一節的總結,非常適合初學者和一些對索引知識認識不夠系統的人學習。由於相關圖片資源無法直接轉存到CSDN,就不單獨處理了,直接貼一下有道雲筆記外部地址。歡迎點評和評論,共同成長!
http://note.youdao.com/noteshare?id=5d27ff2f8a96c6cf03bcf8a3fc851063

第一節、深入淺出的認識Mysql索引

寫在前面的話

正確的創建合適的索引,是提升數據庫查詢性能的基礎

一、Mysql體系結構圖

二、認識索引

1、索引是什麼

索引是爲了加速對錶中數據行的檢索而創建的一種分散存儲的數據結構。

2、爲什麼要用索引

  • 索引能極大的減少存儲引擎需要掃描的數據量
  • 索引可以把隨機IO變成順序IO
  • 索引可以幫助我們在進行分組、排序等操作時,避免使用臨時表

三、爲什麼選擇B+Tree

1、二叉查找樹

缺點:層次太深,極端情況可能出現鏈表的情況,時間複雜度O(logn)-O(n)

2、平衡二叉查找樹

關鍵字:索引列上對應的值

數據區:存放磁盤物理數據或者物理數據的磁盤地址

子節點引用:指向下一子節點的地址

缺點:

  • 它太深了。數據處的(高)深度決定了它的IO次數,IO操作耗時大
  • 它太小了。
    • 每一個磁盤塊(節點/頁)保存的數據量太小了。(操作系統默認每次從磁盤交換一頁(通常爲4K)的數據到內存)
    • 無法很好的利用操作磁盤IO的數據交換特性,也沒有很好的利用磁盤IO的預讀能力(空間局部性原理),從而帶來頻繁的IO操作

通俗的話解釋“空間局部性原理”,當向磁盤交換某個地址的數據時,操作系統會認爲馬上可能會用到上一頁/下一頁的數據,會提前預加載,所以每次交換的數據往往不只一頁

3、多路平衡查找樹

計算公式:

  • N = (16*1024-Z)/(X+Y+Z)
  • M = N+1

Mysql默認每頁數據大小爲16K,1K=1024Byte

N:節點存儲關鍵字的數量

X:單個關鍵字存儲所佔物理空間大小

Y:單個數據區存儲所佔物理空間大小

Z:單個子節點引用存儲所佔物理空間大小

M:平衡查找樹的寬度(路數)

參考舉例:假設我們採用int類型的id列作爲索引,int類型的值佔用4byte長度的大小,將單個數據區和子節點引用所佔物理空間大小約等於4byte,那麼粗略計算出N約等於2000,每個節點可以保存2000關鍵字的數量,將大大降低樹的深(高)度。

優點:

  • 天然的是絕對平衡樹(數據插入到葉子節點,不平橫時向上提升)
  • “矮胖型”的樹降低了樹的深(高)度
  • 每個節點保存的數據更大,很好的利用空間局部性原理

4、Mysql選擇的B+樹

B樹與B+樹的區別:

  • B+樹節點關鍵字搜索採用閉合區間(每個節點搜索都需要搜索到葉子節點)
  • B+樹非葉節點不保存數據相關信息,只保存關鍵字和子節點的引用(能夠存放關鍵字的數量更多,Mysql中默認每頁加載數據大小16K,索引字段佔用越小,數據區越小(B+樹非葉子節點不保存數據),可以使得整棵樹更加“矮胖”,樹的深(高)度越淺(低),檢索時間複雜度越低,這也是爲什麼表定義字段時建議索引字段長度能給小盡量給小)
  • B+關鍵字對應的數據保存在葉子節點中(數據存儲更加集中,相鄰數據集中了更多順序IO)
  • B+葉子節點是順序排列的,並且相鄰節點具有順序引用的關係(數據存儲天然自帶排序)

選擇B+樹的優勢

  • B+樹是B-樹(B樹)的一個增強版(多路絕對平衡查找樹),同樣具備B-樹的優勢
  • B+樹掃庫、表能力更強(只需要掃葉子節點)
  • B+樹的磁盤讀寫能力更強(更多的順序IO)
  • B+樹的排序能力更強(數據存儲默認按照索引關鍵字有序)
  • B+樹的查詢效率更加穩定(仁者見仁、智者見智。B樹搜索節點存在不確定性,可能在根節點、中間節點、葉子節點,如果樹的深(高)度很深(高),檢索到節點關鍵字所耗時差異較大。而B+樹每次檢索數據都需要檢索到葉子節點)

四、Mysql B+Tree索引體現形式

1、各種存儲引擎在Mysql中數據存儲文件

.frm存儲表定義文件。每種存儲引擎都有的一個表定義(創建表的語句,字段及字段大小、字段約束等等)文件。

Mysql存儲引擎是提供一套原子API方式,具體交給第三方實現,通過插拔式適配到Mysql中,作用於表<每個表都可以選擇不同的存儲引擎,在創建表時可顯示指定存儲引擎>,後續文章再對各大存儲引擎做詳細介紹。

MyISAM存儲引擎(Mysql5.5版本之前默認的存儲引擎)

  • .MYI存儲表索引
  • .MYD存儲表數據

InnoDB存儲引擎(Mysql5.5版本之後默認的存儲引擎)

  • .idb存儲表索引及表數據文件(聚集索引/聚簇索引)

MEMORY存儲引擎

  • 數據存儲在內存中。Mysql中臨時表所採用的存儲引擎,默認單表數據最大16M,超過則選擇MyISAM引擎

MERGE存儲引擎

  • 是一組MyISAM表組合

ARCHIVE存儲引擎

  • .ARZ採用壓縮的方式存儲表數據文件(提供參考數據:MyISAM引擎中單表數據100萬,佔用空間大小104M,在ARCHIVE引擎同樣的數據佔用磁盤空間3M)

2、B+Tree在MyISAM中體現形式

 

特點:

  • 索引之間關係平等(沒有物理的主輔關係)
  • 索引和數據單獨存儲,劃分明確,容易理解
  • 節點數據區保存數據的物理磁盤地址

3、B+Tree在InnoDB中體現形式

 

特點:

  • 採用聚集索引存儲索引和數據文件
  • 輔助索引葉子節點存儲主鍵索引的關鍵字
  • 當表未定義主鍵時,使用唯一索引作爲主鍵索引,當未定義主鍵和唯一索引時,會默認生成6byte的自增數字id(隱藏)作爲主鍵索引,InnoDB認爲主鍵是非常重要且常用的檢索數據條件

4、MyISAM和InnoDB對比

四、索引知識補充

1、列的離散性(重複度)

答案:name>zoneDesc>sex

計算公式:count(distinct col):count(col) 不重複的數量/總數

結論:列的離散性越高,選擇性就越好。sql優化器在檢索數據時發現離散性很差時,可能會選擇全表掃描,創建索引時儘量選擇離散性高的列(字段)作爲索引

2、最左匹配原則

3、聯合索引

往往實踐中設計聯合索引時原則是:最常用優先>離散性高優先>寬度小優先

場景實踐:

通過最左匹配原則,當通過name字段檢索時同樣可命中聯合索引,此時單獨創建name字段作爲索引是冗餘的表現,減少冗餘索引的設計,可提高DML語句的效率

select * from user where phoneNum=‘1378’ and username='李二狗'不會命中索引

4、覆蓋索引

如果查詢列可通過索引節點中的關鍵字直接返回,則該索引稱之爲覆蓋索引。

  • 通俗的話解釋就是查詢的字段就是索引關鍵字,此時可直接返回索引關鍵字而不用檢索到葉子節點。

覆蓋索引可減少數據庫IO,將隨機IO變爲順序IO,可提高查詢效率。

通過上例我們發現:select name,phoneNum from user where name='李二狗' and phoneNum=‘1378’;此時就可能命中覆蓋索引,如果是select * from user where username='李二狗'此時就一定不會命中覆蓋索引,所以很多實際場景和公司禁止使用 “*”作爲查詢字段,比如58同城的“58條軍規”就嚴令禁止。

5、知識運用和總結

  • 索引列的字段長度能少則少
  • 索引不是越多越好,越全越好,一定是建立合適的索引
  • 匹配列前綴可能用到索引 like 999%(離散性差時也會全表掃描),like %99%、like %999用不到索引
  • WHERE條件中not in 和<>(!=) 操作無法使用索引
  • 匹配範圍值,order by也可能用到索引
  • 多用指定列查詢,只返回自己想要的數據列,少用select *(根據實際場景)
  • 聯合索引中如果不是按照索引最左列開始查找,無法使用索引
  • 聯合索引中精確匹配最左前列並範圍匹配另外一列時可以用到索引
  • 聯合索引中如果查詢中有某個列的範圍查詢,則其右邊的所有列都無法使用索引

 

最後總結成一首打油詩獻給大家:

全值匹配我最愛,最左前綴要遵守;

帶頭大哥不能死,中間兄弟不能斷;

索引列上少計算,範圍之後全失效;

LIKE百分寫最右,覆蓋索引不寫星;

不等空值還有OR,索引失效要少用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章