MySQL索引(1)存儲引擎和底層數據結構


在昨天的面試中問到了MySQL索引怎么優化(查詢很慢怎么辦),回答的很不理想,所以今天來總結幾篇關於MySQL索引的知識。

1.什么是索引?

首先我們一定要明確什么是索引?我自己的總結就是索引是一種數據結構,可以幫助我們快速訪問數據庫的指定信息,就像一本書的目錄一樣,可以加快查詢速度

2.MySQl存儲引擎

MySQL中最常見的存儲引擎有InnoDB和MyISAM,它們的主要區別如下:

  • MyISAM不支持事務;InnoDB是事務類型的存儲引擎。
  • MyISAM只支持表級鎖;InnoDB支持行級鎖和表級鎖,默認為行級鎖。
  • MyISAM引擎不支持外鍵;InnoDB支持外鍵。
  • 對於count(*)查詢來說MyISAM更有優勢,因為其保存了行數。
  • InnoDB是為處理巨大數據量時的最大性能設計的存儲引擎。
  • MyISAM支持全文索引(FULLTEXT);InnoDB不支持。

總結:

最主要的區別就是MyISAM表不支持事務、不支持行級鎖、不支持外鍵。 InnoDB表支持事務、支持行級鎖、支持外鍵。

在MySQL5.5.5版本之后,InnoDB已經成為了其默認的存儲引擎,也是大部分公司的不二選擇,畢竟誰家公司會不要求數據庫支持事務呢?誰家公司又可以忍受表級鎖導致的讀寫沖突呢?

除了InnoDB以及MyISAM存儲引擎外,常見的考察存儲引擎還有Memory,使用Memory作為存儲引擎的表也可以叫做內存表,將數據存儲在了內存中,所以適合做臨時表來使用,在索引結構上支持B+樹索引和Hash索引。

3.為什么選擇B+樹索引

這里推薦一個外國的學習數據結構的一個網站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html(非常的nice)

首先列舉幾個可以做索引的數據結構:

  1. 二叉查找樹
  2. 紅黑樹
  3. B樹
  4. B+樹

1.平衡二叉查找樹(AVL樹)

 

看一下最基本的結構,這里我也是插入了7個數據

說一下特征:

  1. 非葉子結點最多有兩個子結點
  2. 非葉子結點大於左邊子結點,小於右邊子結點
  3. 沒有值相等重復的點
  4.  每個節點的左子樹和右子樹的高度差至多為1

它的體現在哪里呢?

比如說我們查詢3:3是小於根節點4的,從它的左子樹找,3是大於2的,所以在2的右子樹,這樣就查詢到3的位置了,查詢速度為O(LogN)

缺點:維護平衡二叉樹的代價太大每次都需要左旋或者右旋來維持平衡

2.紅黑樹

 

 

 插入10后

 

 

 

特征:

  1. 每個節點或者是黑色,或者是紅色。
  2. 根節點是黑色。
  3. 每個葉子節點(NIL)是黑色。 [注意:這里葉子節點,是指為空(NIL或NULL)的葉子節點!]
  4. 如果一個節點是紅色的,則它的子節點必須是黑色的。
  5. 從一個節點到該節點的子孫節點的所有路徑上包含相同數目的黑節點。[這里指到葉子節點的路徑]

 

到這里我們要說到一些東西

磁盤IO

計算機硬件性能在過去十年間的發展普遍遵循摩爾定律,通用計算機的CPU主頻早已超過3GHz,內存也進入了普及DDR4的時代。然而傳統硬盤雖然在存儲容量上增長迅速,但是在讀寫性能上並無明顯提

升,同時SSD硬盤價格高昂,不能在短時間內完全替代傳統硬盤。傳統磁盤的I/O讀寫速度成為了計算機系統性能提高的瓶頸,制約了計算機整體性能的發展。

其實簡單來說就是我們要減少磁盤IO的次數,樹的深度越大,磁盤IO的次數就越多,所以無論是從它的平衡代價或者磁盤IO次數來講紅黑樹和AVL樹都太適合。

局部性原理與磁盤預讀:

由於存儲介質的特性,磁盤本身存取就比主存慢很多,再加上機械運動耗費,磁盤的存取速度往往是主存的幾百分分之一,因此為了提高效率,要盡量減少磁盤I/O。為了達到這個目的,磁盤往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個字節,磁盤也會從這個位置開始,順序向后讀取一定長度的數據放入內存。這樣做的理論依據是計算機科學中著名的局部性原理:
當一個數據被用到時,其附近的數據也通常會馬上被使用。
程序運行期間所需要的數據通常比較集中。
由於磁盤順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對於具有局部性的程序來說,預讀可以提高I/O效率。


紅黑樹這種結構,h明顯要深的多。由於邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性,所以紅黑樹的I/O漸進復雜度也為O(h),效率明顯不太盡人意。

3.B樹

一個M階的b樹具有如下幾個特征:

  1. 定義任意非葉子結點最多只有M個兒子,且M>2;
  2. 根結點的兒子數為[2, M];
  3. 除根結點以外的非葉子結點的兒子數為[M/2, M],向上取整;
  4. 非葉子結點的關鍵字個數=兒子數-1;
  5. 所有葉子結點位於同一層;
  6. k個關鍵字把節點拆成k+1段,分別指向k+1個兒子,同時滿足查找樹的大小關系。

特性

  1. 關鍵字集合分布在整顆樹中;
  2. 任何一個關鍵字出現且只出現在一個結點中;
  3. 搜索有可能在非葉子結點結束;
  4. 其搜索性能等價於在關鍵字全集內做一次二分查找;

4.B+樹

M階的b+樹的特征:

  1. 有n棵子樹的非葉子結點中含有n個關鍵字(b樹是n-1個),這些關鍵字不保存數據,只用來索引,所有數據都保存在葉子節點(b樹是每個關鍵字都保存數據)。
  2. 所有的葉子結點中包含了全部關鍵字的信息,及指向含這些關鍵字記錄的指針,且葉子結點本身依關鍵字的大小自小而大順序鏈接。
  3. 所有的非葉子結點可以看成是索引部分,結點中僅含其子樹中的最大(或最小)關鍵字。
  4. 通常在b+樹上有兩個頭指針,一個指向根結點,一個指向關鍵字最小的葉子結點。
  5. 同一個數字會在不同節點中重復出現,根節點的最大元素就是b+樹的最大元素。

B+樹相對於B樹的優勢

  1. b+樹的中間節點不保存數據,所以磁盤頁能容納更多節點元素,更“矮胖”;
  2. b+樹查詢必須查找到葉子節點,b樹只要匹配到即可不用管元素位置,因此b+樹查找更穩定(並不慢);
  3. 對於范圍查找來說,b+樹只需遍歷葉子節點鏈表即可,b樹卻需要重復地中序遍歷,如下兩圖:

4.總結

數據庫引擎:InnoDB和MyISAM

主要區分:事務,外鍵,行級鎖(以上InnoDB都支持,MyISAM只支持表級鎖)

為什么選擇B+樹:

  1. AVL樹和紅黑樹深度深,磁盤IO次數多,父子節點物理上遠,不滿足局部性原理
  2. B+樹,非葉子節點不保存數據,葉子結點之間有指針可以進行范圍查找,並且B+樹里的元素也是有序的。

附加問題:

B+樹中一個節點到底多大合適?

B+樹中一個節點為一頁(16KB)或頁的倍數最為合適。

因為如果一個節點的大小小於1頁,那么讀取這個節點的時候其實也會讀出1頁,造成資源的浪費。

如果一個節點的大小大於1頁,比如1.2頁,那么讀取這個節點的時候會讀出2頁,也會造成資源的浪費。

所以為了不造成浪費,所以最后把一個節點的大小控制在1頁、2頁、3頁、4頁等倍數頁大小最為合適。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM