面試官這樣問你:為什麼MySQL新增索引後就可以提高查詢速度

php自學中心發表於2021-01-22

面試中面試官問你啥問題,小編都給你整理在這裡了。每天都會整理一份最接地氣的面試題,希望能幫助到你!
同時帶上一套視訊教程【帶你橫掃PHP職場 全面解讀PHP面試】,感謝你閱讀這篇文章!
關注公眾號:PHP面試題,回覆:160705 即可獲取。
文章來自:baijiahao.baidu.com/s?id=164443196...



遇到這種問題,你就要高度集中,保持空杯心態,腦海裡要有以下三個問題

1 為什麼新增索引會提高查詢速度

2 索引提高了查詢速度對增刪改有影響

3 索引常用的演算法原理分析B樹和B+樹


下面來詳細介紹介紹
為什麼新增索引會提高查詢速度

一句話回答:索引可以將無序內容轉換為有序的一個集合(相對),就如同新華字典,如果沒有目錄,那麼查詢一個漢字就需要很長時間了。

MySQL 使用的是 Btree 索引,那它是怎麼加速檢索的呢?

檢索中主要耗時在於記憶體與磁碟的IO耗時,所以加速的關鍵在於減少IO的次數。

圖片

圖中是一顆 b 樹,每個磁碟塊包含幾個資料項和指標,

如磁碟塊 1 包含資料項 17 和 35,包含指標 P1、P2、P3,

P1指向包含資料項小於17的磁碟塊,P2指向資料項在17和35之間的磁碟塊,P3 指向資料項大於35的磁碟塊。

真實的資料存在於葉子節點,即 3、5、9、10、13、15、28、29、36、60、75、79、90、99。

非葉子節點只不儲存真實的資料,只儲存指引搜尋方向的資料項,如 17、35 並不真實存在於資料表中。


【查詢過程】 以查詢資料項29為例

  1. 首先會把磁碟塊 1 由磁碟載入到記憶體,此時發生一次 IO,在記憶體中用二分查詢確定29在17和35之間,鎖定磁碟塊1的 P2指標,相比磁碟的 IO,記憶體時間非常短可以忽略不計。

  2. 通過磁碟塊 1的 P2 指標的磁碟地址把磁碟塊 3 由磁碟載入到記憶體,發生第二次 IO,29 在 26 和 30 之間,同理鎖定磁碟塊 3 的 P2 指標。

  3. 通過指標載入磁碟塊 8 到記憶體,發生第三次 IO,同時記憶體中做二分查詢找到了資料項 29,結束查詢,總計三次 IO。

真實的情況中,3 層的樹可以表示上百萬的資料,上百萬的資料查詢只需要三次 IO,效能提高是巨大的,速度自然很快。相反如果沒有索引,那就要遍歷所有資料,最差情況下每個資料項都要發生一次 IO,那麼總共需要百萬次的 IO,速度自然很慢。


索引可以提高查詢速度,但是會降低增刪改的速度,為什麼

任何事情都有有利有弊,在於你自己權衡利弊。

首先來說B+樹就是平衡樹的一種。

NOTE:平衡樹它就是一顆空樹或者說它左右兩個子樹的高度相差的絕對值不會超過1,並且左右兩個子樹都是一顆平衡二叉樹。

如果一棵普通B樹在極端情況下是有可能退化成連結串列的,這樣所謂的查詢提速也就不存在了

圖片

前面我們就說了B+樹本身就是平衡樹,所以它是不會退化成連結串列的,樹的高度都是比較低的(矮胖墩)【正因為這一點,我們的檢索時間複雜度為O】,在上面新增索引會提高查詢速度中我們介紹的建立索引,說白了就是建立一個B+樹。

  • B+樹是一顆平衡樹,如果我們對這棵樹增刪改的話,那肯定會破壞它的原有結構。

  • 要維持平衡樹,就必須做額外的工作。正因為這些額外的工作開銷,導致索引會降低增刪改的速度


索引常用的演算法原理分析:B樹和B+樹等

和索引相關的演算法:二分查詢法、二叉查詢樹、平衡二叉樹、B樹、B+樹,內容長,但很有用,如果看、請耐心點!

我們在這些數字中用不同演算法(1、2、3、5、6、7、9)找出6。

二分查詢法原理:先將記錄按順序排列,查詢時先按序列的中點位置為比較物件,如果要找的元素值小於該中點元素,則將查詢範圍縮小為左半部分;如果要找的元素值大於該中點元素,則將查詢範圍縮小為右半部分。以此類推,直到查到需要的值。

圖片

比如我們要找6,用了 3 次就查詢到 6 這個數字了。如果是順序查詢,則需要查詢 5 次(從第一個數字 1 開始,如果發現不是 6,則繼續查詢下一個,直到查詢到 6)。

我們來對比一下這個例子順序查詢和二分查詢法的平均查詢次數:

順序查詢:(1 + 2 + 3 + 4 + 5 + 6 + 7)/7 = 4 次

二分查詢法:(3 + 2 + 3 + 1 + 3 + 2 + 3)/7 ≈ 2.4 次

顯然二分查詢法相對順序查詢平均效率更高。

二叉樹查詢原理:二叉查詢樹中,左子樹的鍵值總是小於根的鍵值,右子樹的鍵值總是大於根的鍵值,並且每個節點最多隻有兩顆子樹。

圖片

還是找6,這組數字的平均查詢次數為:(3 + 2 + 1 + 2 + 3 + 4 + 5)/7 ≈ 2.9 次

試想一下,如果 3 的右子樹後面拖更多的數字,那查詢效率得多低啊!

此時,平衡二叉樹出場了。

平衡二叉樹的定義:滿足二叉查詢樹的定義,另外必須滿足任何節點的兩個子樹的高度差最大為 1。

圖片

如果要查值為 6 的記錄,先找到根(這裡是 5 ),這裡借用二分查詢的思想,因為要找的值 6 大於中點元素 5,所以需要查詢的是 5 的右子樹,而又因為 6 小於 7,則應該找 7 的左子樹,找到 6 這條記錄,一共查詢了 3 次。如果查詢記錄使用順序查詢,找到 6 這個值需要查 5 次。

平衡二叉查詢樹的平均查詢次數:(3 * 4 + 2 * 2 + 1) /7 ≈ 2.4 次

計算方式:該平衡二叉查詢樹中 4 個第三層的值需要查詢 3 次,2 個第二層的值需要查詢 2 次,第一層也就是根的值只需要查 1 次。

上面我們說了順序查詢需要查詢4次,比起來顯然平衡二叉查詢樹的平均查詢速度比順序查詢更快。

但是平衡二叉樹有個缺點就是,每個節點最多隻有兩個分支,如果資料量比較大,要經歷多層節點才能查詢在葉子節點的資料。

如果在平衡二叉樹的基礎上,每個節點可以有多個分支,那即使在葉子節點的資料,是不是查詢效率也比較高呢?這就引出了 B 樹結構。

B 樹可以理解為一個節點可以擁有多於 2 個子節點的多叉查詢樹。B 樹中同一鍵值不會出現多次,要麼在葉節點,要麼在葉的子節點上。

比如用 1、2、3、5、6、7、9 這些數字構建一個 B 樹結構,其圖形如下:

圖片

與平衡二叉樹相比,B 樹利用多個分支(平衡二叉樹只有兩個分支)節點,減少獲取記錄時所經歷的節點數。

B 樹也是有缺點,因為每個節點都包含 key 值和 data 值,因此如果 data 比較大時,每一頁儲存的 key 會比較少;當資料比較多時,同樣會有:“要經歷多層節點才能查詢在葉子節點的資料”的問題。這時,B+ 樹站了出來。

B+ 樹是 B 樹的變體,定義基本與 B 樹一致


B樹和B+樹不同點:

  • 所有葉子節點中包含了全部關鍵字的資訊各葉子節點用指標進行連線非葉子節點上只儲存 key 的資訊,這樣相對 B 樹,可以增加每一頁中儲存 key 的數量。

  • B 樹是縱向擴充套件,最終變成一個“瘦高個”,而 B+ 樹是橫向擴充套件的,最終會變成一個“矮胖子”。

在 B+ 樹中,所有記錄節點都是按鍵值的大小順序存放在同一層的葉子節點上。B+ 樹中的 B 不是代表二叉(binary) 而是代表(balance),B+ 樹並不是一個二叉樹。

圖片

B+與B樹最大的區別就是:B+樹它的鍵一定會出現在葉子節點上,同時也有可能在非葉子節點中重複出現。而 B 樹中同一鍵值不會出現多次。


總結

到此為止基本mysql查詢演算法就全部講完了,下一篇我們主要來看mysql的聚簇索引和非聚簇索引。



以上是本文的全部內容,希望對大家的學習有幫助,覺得有用,有需要就支援一下吧!助你面試成功 拿下高薪崗位

圖片

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章