1. 程式人生 > 其它 >《MySQL面試小抄》索引考點二面總結

《MySQL面試小抄》索引考點二面總結

《MySQL面試小抄》索引考點二面總結

我是肥哥,一名不專業的面試官!

我是囧囧,一名積極找工作的小菜鳥!

囧囧表示:小白麵試最怕的就是面試官問的知識點太籠統,自己無法快速定位到關鍵問題點!!!


本期主要面試考點

面試官考點之談談索引維護過程?頁分裂?頁合併?
面試官考點之簡述一下查詢時B+樹索引搜尋過程?
面試官考點之什麼是回表?
面試官考點之什麼是索引覆蓋?使用場景?
面試官考點之什麼情況下會索引失效?
面試官考點之哪些情況下,可能會面臨索引失效的問題?
面試官考點之or走索引和索引失效分別是什麼場景?
面試官考點之哪些情況下需要建立索引?
面試官考點之聯合索引之最左字首原則?
面試官考點之索引下推場景?



面試官考點之談談索引維護過程?頁分裂?頁合併?

B+樹為了維護索引有序性,在插入刪除的時候需要做必要的維護,必要時候可能涉及到頁分裂,頁合併過程!

首先假設每個葉子節點(資料頁或磁碟塊)只能儲存3條索引和資料記錄,如圖

情況1、新增行記錄,ID=3,此時【資料頁1】未滿,只需要在data2後新增ID=3的行記錄,B+樹整體結構不需要進行調整

情況2、新增行記錄,ID=8,此時【資料頁2】已滿,這時候需要申請一個新的資料頁,然後挪動部分資料過去。這個過程稱為頁分裂

頁分裂過程消耗效能,同時空間利用率也降低了

有分裂就有合併,當相鄰兩個頁由於刪除了資料,利用率很低之後,會將資料頁做合併。合併的過程,可以認為是分裂過程的逆過程

當相鄰兩個頁由於刪除了資料,利用率很低之後,會將資料頁做合併。合併的過程,可以認為是分裂過程的逆過程。

【資料頁2】刪除了ID=7,ID=8的行記錄,此時【資料頁2】【資料頁3】利用率很低,將進行頁合併。

面試官考點之簡述一下查詢時B+樹索引搜尋過程?

準備一張使用者表,其中id為主鍵,age為普通索引

CREATE TABLE `user` (
`id` int(11) PRIMARY KEY,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL
KEY `idx_age` (`age`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

select * from user where age=22 簡述一下B+樹索引搜尋過程?

假設要查詢的記錄

 id=5,name="張三",age=22

MySQL為每個索引分別維護了一棵B+Tree索引樹,

主鍵索引非葉子節點維護了索引鍵,葉子節點儲存行資料;

非主鍵索引也稱為二級索引,非葉子節點儲存主鍵;

B+樹索引搜尋過程

搜尋條件 age=22,可走idx_age索引,首先載入idx_age索引樹,找到age=22的記錄,取得id=5

回表搜尋,載入主鍵索引樹,找到id=22的記錄,取得整行資料

面試官考點之什麼是回表?

idx_age二級索引樹找到主鍵id後,回到id主鍵索引搜尋的過程,就稱為回表。

並非所有非主鍵索引搜尋,都需要進行回表搜尋,也就是下面要說的索引覆蓋。

面試官考點之什麼是索引覆蓋?使用場景?

在上面提到的例子中,由於查詢結果所需要的資料只在主鍵索引上有,所以不得不回表。

如果在查詢的資料列裡面,直接從索引列就能取到想要的結果,就不需要再回表去查,也稱之為索引覆蓋!

索引覆蓋的優點

  1. 可以避免對Innodb主鍵索引的二次查詢

  2. 可以避免MyISAM表進行系統呼叫

  3. 可以優化快取,減少磁碟IO操作

修改一下上述栗子,滿足索引覆蓋條件?

select id, age from user where age=22

查詢的資訊,id,age都可以直接在idx_age 索引樹中獲取,不需要回表搜尋。

由於覆蓋索引可以減少樹的搜尋次數,顯著提升查詢效能,所以使用覆蓋索引是一個常用 的效能優化手段。

索引是一把雙刃劍,提供快速排序搜尋的同時,索引欄位的維護也是要付出相應的代價的。

因此,在建立冗餘索引來支援覆蓋索引時就需要權衡考慮了

面試官考點之索引失效?

建立的索引,到底有沒有生效,或者說SQL語句有沒有使用索引查詢?

一個最常見的查詢場景,建立idx_name索引

select * from t_user where user_name like '%mayun100%';

這條查詢是否走索引?

select * from t_user where user_name like 'mayun100%';

這條查詢是否走索引?

面試官考點之有哪些情況下,可能會面臨索引失效的問題?

  1. like萬用字元,左側開放情況下,全表掃描

  2. or條件篩選,可能會導致索引失效

  3. where中對索引列使用mysql的內建函式,一定失效

  4. where中對索引列進行運算(如,+、-、*、/),一定失效

  5. 型別不一致,隱式的型別轉換,導致的索引失效

  6. where語句中索引列使用了負向查詢,可能會導致索引失效 負向查詢包括:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等。其中!< !> 為SQLServer語法。

  7. 索引欄位可以為null,使用is null或is not null時,可能會導致索引失效

  8. 隱式字元編碼轉換導致的索引失效

  9. 聯合索引中,where中索引列違背最左匹配原則,一定會導致索引失效

  10. MySQL優化器的最終選擇,不走索引

面試官考點之or走索引和索引失效分別是什麼場景?

or走索引和索引失效分別是什麼場景?

OR 連線的是同一個欄位,相同走索引

explain select * from t_user where user_name = 'mayun10' or user_name = 'mayun1000'

OR 連線的是兩個不同的欄位,不走索引

給address列增加索引

alter table t_user add index idx_address(address);
explain select * from t_user where user_name = 'mayun10' or address = '浙江杭州12';

OR 連線的是兩個不同欄位,如果兩個欄位皆有索引,走索引

(插播,下一期:《MySQL面試小抄》幾種索引失效場景驗證)

盡請關注:囧麼肥事

面試小抄系列。

面試官考點之哪些情況下需要建立索引?

1.主鍵自動建立唯一索引

2.頻繁查詢的欄位

3.JOIN 關聯查詢,作為外來鍵關係的列建立索引

4.單鍵/組合索引的選擇問題,高併發下傾向建立組合索引,建立時遵循最左字首匹配原則

5.ORDER BY 查詢中排序的欄位,排序欄位通過索引訪問大幅提高排序速度

6.GROUP BY 需要分組欄位或查詢中統計欄位

面試官考點之聯合索引之最左字首原則

MySQL建立多列索引(聯合索引)有最左字首的原則,即最左優先

當MySQL建立的是聯合索引,假設以(a,b,c) 列作為聯合索引,那麼MySQL建樹規則是什麼?

我們知道MySQL會為每一個索引維護一顆B+Tree,非葉子節點儲存索引key,葉子節點儲存行資料data。

聯合索引(a,b,c) 相當於建立了 (a), (a,b), (a,b,c) 三個索引,MySQL組裝索引樹時,是按照從左到右的順序來建立B+Tree的聯合索引樹的。

匹配索引情況一

假設(a,b,c)索引要搜尋的值為('張三', 21, 100) ,檢索資料時,匹配的順序就是a,b,c。

B+Tree會優先比較a來確定下一步的所搜方向,如果a相同再依次比較b和c,最後得到檢索的資料;

匹配索引情況二

假設(a,c)索引要搜尋的值為('張三', 100) ,檢索資料時,匹配的順序就是a,b,c。

B+Tree使用a來指定搜尋方向,但下一個欄位b缺失,所以只能把a等於張三的資料都找到,然後再匹配c是100的資料。

匹配索引情況三

假設(b,c)索引要搜尋的值為('張三', 21) ,檢索資料時,無匹配順序

B+Tree不知道下一步該查哪個節點,因為建立搜尋樹的時候a是第一個比較因子,必須要先根據a來搜尋才能知道下一步去哪裡查詢。此時索引失效!

索引項是按照索引定義裡面出現的欄位順序排序的,最左字首可以是聯合索引的最左N個欄位,也可以是字串索引的最左M個字元。

面試官考點之索引下推場景?

索引下推,即減少二級索引回表搜尋次數!!!

通俗說,減少查詢主鍵索引樹次數,減少磁碟IO

建立聯合索引 idx_age_weight

select * from user where age = 11 and weight = 98

5.6之前搜尋過程是

在idx_age_weight 索引樹中匹配出所有的 age = 11 索引,拿到主鍵id,回表去一條條再比對weight欄位

如下圖,需要進行3次回表搜尋操作

5.6後的搜尋過程是 在idx_age_weight 索引樹中匹配出所有的 age = 11 索引,順便對weight欄位進行判斷,過濾掉weight = 100的記錄,然後再進行回表搜尋。

如下圖,只需要進行2次回表搜尋操作

隨緣更新,大神請繞路!

更多精彩內容,歡迎關注微信公眾號:囧麼肥事 (或搜尋:jiongmefeishi)