1. 程式人生 > >MySql面試總結第一部分:B,B+,引擎,索引

MySql面試總結第一部分:B,B+,引擎,索引

1為什麼用B/B+樹這種結構來實現索引呢??

答:紅黑樹等結構也可以用來實現索引,但是檔案系統及資料庫系統普遍使用B/B+樹結構來實現索引。mysql是基於磁碟的資料庫,索引是以索引檔案的形式存在於磁碟中的,索引的查詢過程就會涉及到磁碟IO消耗,磁碟IO的消耗相比較於記憶體IO的消耗要高好幾個數量級,所以索引的組織結構要設計得在查詢關鍵字時要儘量減少磁碟IO的次數。

2為什麼mysql的索引使用B+樹而不是B樹呢??(區別)

1)B+樹更適合外部儲存(一般指磁碟儲存),由於內節點(非葉子節點)不儲存data,所以一個節點可以儲存更多的內節點,每個節點能索引的範圍更大更精確。也就是說使用B+樹單次磁碟IO的資訊量相比較B樹更大,IO效率更高。
2)mysql是關係型資料庫,經常會按照區間來訪問某個索引列,B+樹的葉子節點間按順序建立了鏈指標,加強了區間訪問性,所以B+樹對索引列上的區間範圍查詢很友好。而B樹每個節點的key和data在一起,無法進行區間查詢。
3)B+樹同時支援隨機檢索和順序檢索;
5)B+樹的查詢效率更加穩定。
B樹在提高了磁碟IO效能的同時並沒有解決元素遍歷的效率低下的問題。
B+樹的葉子節點使用指標順序連線在一起,只要遍歷葉子節點就可以實現整棵樹的遍歷。而且在資料庫中基於範圍的查詢是非常頻繁的,而B樹不支援這樣的操作(或者說效率太低)。順序指標:目的是為了提高區間訪問的效能。

3.B樹 是一種平衡的多路搜尋樹。

特點:1.定義任意非葉子結點最多隻有M個兒子;且M>2;
2.根結點的兒子數為[2, M];
3.除根結點以外的非葉子結點的兒子數為[M/2, M];
4.每個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字)
5.非葉子結點的關鍵字個數=指向兒子的指標個數-1;
6.非葉子結點的關鍵字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
7.非葉子結點的指標:P[1], P[2], …, P[M];其中P[1]指向關鍵字小於K[1]的子樹,P[M]指向關鍵字大於K[M-1]的子樹,其它P[i]指向關鍵字屬於(K[i-1],K[i])的子樹;
8.所有葉子結點位於同一層;

4.B+樹—多路搜尋樹

B+樹是是一個n叉樹,每個節點通常有多個孩子,一棵B+樹包含根節點、內部節點和葉子節點。根節點可能是一個葉子節點,也可能是一個包含兩個或兩個以上孩子節點的節點。
B+ 樹的特點是能夠保持資料穩定有序,其插入與修改擁有較穩定的對數時間複雜度。B+ 樹元素自底向上插入。
B+樹是B-樹的變體,也是一種多路搜尋樹:
1.其定義基本與B-樹相同,除了:
2.非葉子結點的子樹指標與關鍵字個數相同;
3.非葉子結點的子樹指標P[i],指向關鍵字值屬於[K[i], K[i+1])的子樹(B-樹是開區間);
5.為所有葉子結點增加一個鏈指標;
6.所有關鍵字都在葉子結點出現; B+的特性:
1.所有關鍵字都出現在葉子結點的連結串列中(稠密索引),且連結串列中的關鍵字恰好是有序的;
2.不可能在非葉子結點命中;
3.非葉子結點相當於是葉子結點的索引(稀疏索引),葉子結點相當於是儲存(關鍵字)資料的資料層;
4.更適合檔案索引系統;

5.MYISAM和INNODB的不同?

幾點區別:
a)構造上的區別
MyISAM在磁碟上儲存成三個檔案,其中.frm檔案儲存表定義;.MYD (MYData)為資料檔案;.MYI (MYIndex)為索引檔案。
innodb是由.frm檔案、表空間(分為獨立表空間或者共享表空間)和日誌檔案(redo log)組成。
b)事務上的區別
myisam不支援事務;而innodb支援事務。
c)鎖上的區別
myisam使用的是表鎖;而innodb使用的行鎖(innodb也支援表鎖)。
表級鎖:直接鎖定整張表,在鎖定期間,其他程序無法對該表進行寫操作,如果設定的是寫鎖,那麼其他程序讀也不允許,因此myisam支援的併發量低,但myisam不會出現死鎖;
行級鎖:只對指定的行進行鎖定,其他程序還是可以對錶中的其他行進行操作的。因此行鎖能大大的減少資料庫操作的衝突,但有時會導致死鎖。
d)是否支援外來鍵的區別
myisam不支援外來鍵,innodb支援外來鍵
e) select count(*)的區別
對於沒有where的count()使用MyISAM要比InnoDB快得多。 MyISAM內建了一個計數器,count()時它直接從計數器中讀,而InnoDB必須掃描全表。
f)myisam只把索引都load到記憶體中,而innodb儲存引擎是把資料和索引都load到記憶體中 ,innodb不支援全文索引(5.7支援),當使用資料庫事務時,innodb引擎是首選。由於鎖的粒度更小,寫操作不會鎖定全表,所以在併發較高時,使用Innodb引擎會提升效率。

6.適用場景

MyISAM適合:(1)做很多count 的計算;(2)插入不頻繁,查詢頻繁;(3)沒有事務。
InnoDB適合:(1)可靠性要求比較高,或者要求事務;(2)表更新和插入都相當的頻繁,並且表鎖定的機會比較大的情況。

7.索引方式
MyISAM:非聚集索引

1)在MyISAM中,主索引和輔助索引(Secondary
key)在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重複。
2)MyISAM中索引檢索的演算法為首先按照B+Tree搜尋演算法搜尋索引,如果指定的Key存在,則取出其data域的值,然後以data域的值為地址,讀取相應資料記錄。
3)MyISAM的索引方式也叫做“非聚集”的.主鍵B+樹在葉子節點儲存指向真正資料行的指標,而非主鍵.

InnoDB(聚集索引)-————-使用B+Tree作為索引結構.

1)InnoDB的資料檔案本身就是索引檔案,這棵樹的葉節點data域儲存了完整的資料記錄。這個索引的key是資料表的主鍵,因此InnoDB表資料檔案本身就是主索引。因為InnoDB的資料檔案本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識資料記錄的列作為主鍵,如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含欄位作為主鍵,這個欄位長度為6個位元組,型別為長整形。
2)InnoDB的輔助索引data域儲存相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域。
3)聚集索引這種實現方式使得按主鍵的搜尋十分高效,但是輔助索引搜尋需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然後用主鍵到主索引中檢索獲得記錄。
4)不建議使用過長的欄位作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。
5)在InnoDB中不建議用非單調的欄位作為主鍵,因為InnoDB資料檔案本身是一顆B+Tree,非單調的主鍵會造成在插入新記錄時資料檔案為了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增欄位作為主鍵則是一個很好的選擇。

8 為什麼MyISAM會比Innodb 的查詢速度快。

1)INNODB在做SELECT的時候,要維護的東西比MYISAM引擎多很多;
2)INNODB快取資料塊,MYISAM只快取索引塊, 這中間還有換進換出的減少;
3)innodb定址要對映到塊,再到行,MYISAM 記錄的直接是檔案的OFFSET,定位比INNODB要快
4)INNODB還需要維護MVCC一致;雖然你的場景沒有,但他還是需要去檢查和維護 —MVCC ( Multi-Version Concurrency Control )多版本併發控制

9.資料庫索引

一個排序的資料結構,以協助快速查詢、更新資料庫表中資料。索引的實現通常是B樹及其變種B+樹。
索引代價:一是增加了資料庫的儲存空間,二是在插入和修改資料時要花費較多的時間(因為索引也要隨之變動)。

10.建立索引的好處:

第一,通過建立唯一性索引,可以保證資料庫表中每一行資料的唯一性。
第二,可以大大加快資料的檢索速度。
第三,可以加速表和表之間的連線,特別是在實現資料的參考完整性方面特別有意義。
第四,在使用分組和排序子句進行資料檢索時,同樣可以顯著減少查詢中分組和排序的時間。
10.1.缺點:

第一,建立索引和維護索引要耗費時間。
第二,索引需要佔物理空間,除了資料表佔資料空間之外,每一個索引還要佔一定的物理空間,如果要建立聚簇索引,那麼需要的空間就會更大。
第三,當對錶中的資料進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了資料的維護速度。

11.什麼情況需要建立索引:

1)在經常需要搜尋的列上,可以加快搜索的速度;
2)在作為主鍵的列上,強制該列的唯一性和組織表中資料的排列結構;
3)在經常用在連線的列上,這些列主要是一些外來鍵,可以加快連線的速度;
4)在經常需要根據範圍進行搜尋的列上建立索引和經常需要排序的列上建立索引,因為索引已經排序,其指定的範圍是連續的;
5)在經常使用在WHERE子句中的列上面建立索引,加快條件的判斷速度。

12.不應該建立索引的情況:

     第一,對於那些在查詢中很少使用列不應該建立索引。------增加了索引,反而降低了系統的維護速度和增大了空間需求。
     第二,對於那些只有很少資料值的列也不應該增加索引。這是因為,由於這些列的取值很少,結果集的資料行佔了表中資料行的很大比例,即需要在表中搜索的資料行的比例很大。(與第五條相似)
     第三,對於那些定義為text, image和bit資料型別的列不應該增加索引。----這些列的資料量要麼相當大,要麼取值很少。
     第四,當修改效能遠遠大於檢索效能時,不應該建立索引。這是因為,修改效能和檢索效能是互相矛盾的。----當修改效能遠遠大於檢索效能時,不應該建立索引。
     第五,索引的選擇性較低不應該建立索引。所謂索引的選擇性(Selectivity),是指不重複的索引值(也叫基數,Cardinality)與表記錄數(#T)的比值:Index Selectivity = Cardinality / #T  顯然選擇性的取值範圍為(0, 1],選擇性越高的索引價值越大,這是由B+Tree的性質決定的。

13.索引類別:

主鍵索引primary key——是一種特殊的唯一索引,一個表只能有一個主鍵,不允許有空值。
唯一索引unique key ——索引列的值必須唯一。
普通索引 key
全文索引 fulltext —–在一堆文字中,通過其中的某個關鍵字等,就能找到該欄位所屬的記錄行。只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT型別欄位上使用全文索引(現在Innodb也支援全文索引了mysql5.7)
全文搜尋的限制比較多,比如只能通過MyISAM引擎,比如只能在CHAR,VARCHAR,TEXT上設定全文索引。比如搜尋的關鍵字預設至少要4個字元,比如搜尋的關鍵字太短就會被忽略掉。
組合索引 – 多個欄位上建立的索引,只有在查詢條件中使用了建立索引時的第一個欄位,索引才會被使用。 使用組合索引時遵循最左字首原則
注:在mysql中執行查詢時,只能使用一個索引,如果我們在lname,fname,age上分別建索引,執行查詢時,只能使用一個索引,mysql會選擇一個最嚴格(獲得結果集記錄數最少)的索引。

——-主鍵索引和唯一索引的區別———

唯一性索引列允許空值,而主鍵列不允許為空值
主鍵可以被其他表引用為外來鍵,而唯一索引不能。
一個表最多隻能建立一個主鍵,但可以建立多個唯一索引。
主鍵建立後一定包含一個唯一性索引,唯一性索引並不一定就是主鍵。

14.建立索引的時機

一般來說,在WHERE和JOIN中出現的列需要建立索引,因為MySQL只對<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE才會使用索引。
以萬用字元%和_開頭作查詢時,MySQL不會使用索引————like’%admin’

15.B和B+兩種處理索引的資料結構的不同之處:

a,B樹中同一鍵值不會出現多次,並且它有可能出現在葉結點,也有可能出現在非葉結點中。而B+樹的鍵一定會出現在葉結點中,並且有可能在非葉結點中也有可能重複出現,以維持B+樹的平衡。
b,因為B樹鍵位置不定,且在整個樹結構中只出現一次,雖然可以節省儲存空間,但使得在插入、刪除操作複雜度明顯增加。B+樹相比來說是一種較好的折中。
c,B樹的查詢效率與鍵在樹中的位置有關,最大時間複雜度與B+樹相同(在葉結點的時候),最小時間複雜度為1(在根結點的時候)。而B+樹的時候複雜度對某建成的樹是固定的。

16.索引結構–聚集索引和非聚集索引

非聚集索引:B+樹索引結構–葉子節點儲存實體地址
聚集索引:B+ 1)主鍵索引:葉子節點儲存整條記錄,而不是物理節點。
2)非主鍵索引:葉子節點儲存的是主鍵索引,通過主鍵索引來查詢記錄。

17.索引優化–最左字首原則

索引條件下:
1)全列匹配,當搜尋的列是索引的全部欄位;此時不需要考慮順序問題,因為MySQL的查詢優化器會自動調整where子句的條件順序以使用適合的索引。
2)最左字首匹配 查詢條件指定了索引的第一列,會使用部分索引; 主索引為< emp_no, title, from_date> 例如
WHERE emp_no=’10001’ 會使用部分索引
WHERE emp_no=’10001’ AND from_date=’1986-06-26’ 會使用部分索引 如果想讓後者也在索引列中,方法一就是建立輔助索引 < emp_no,from_date>,或者“隔離列”的優化方法,將emp_no與from_date之間的“坑”填上;在這種成為“坑”的列值比較少的情況下,可以考慮用“IN”來填補這個“坑”從而形成最左字首WHERE emp_no=’10001’ AND title IN (‘Senior ‘,。。。) AND from_date=’1986-06-26’;“填坑”後效能提升了一點。如果經過emp_no篩選後餘下很多資料,則後者效能優勢會更加明顯。當然,如果title的值很多,用填坑就不合適了,必須建立輔助索引。
WHERE from_date=’1986-06-26’ 不會使用索引 匹配某列字首字串 WHERE emp_no=’10001’ AND title LIKE ‘Senior%’;此時可以用到索引,如果萬用字元%不出現在開頭,則可以用到索引,但根據具體情況不同可能只會用其中一個字首 範圍查詢:
範圍列可以用到索引(必須是最左字首),但是範圍列後面的列無法用到索引。同時,索引最多用於一個範圍列,因此如果查詢條件中有兩個範圍列則無法全用到索引。
查詢條件中含有函式或表示式 如果查詢條件中含有函式或表示式,則MySQL不會為這列使用索引(雖然某些在數學意義上可以使用)

18索引優化—字首索引

與索引選擇性有關的索引優化策略叫做字首索引,就是用列的字首代替整個列作為索引key,當前綴長度合適時,可以做到既使得字首索引的選擇性接近全列索引,同時因為索引key變短而減少了索引檔案的大小和維護開銷。
< first_name, left(last_name, 4)> ADD INDEX first_name_last_name4(first_name, last_name(4)); 字首索引兼顧索引大小和查詢速度,但是其缺點是不能用於ORDER BY和GROUP BY操作,也不能用於Covering index(即當索引本身包含查詢所需全部資料時,不再訪問資料檔案本身)。

19.覆蓋索引概念:

MySQL可以利用索引返回SELECT列表中的欄位,而不必根據索引再次讀取資料檔案。包含所有滿足查詢需要的資料的索引成為覆蓋索引(Covering Index)。也就是平時所說的不需要回表操作。

20.判斷標準:

在查詢前面使用explain,可以通過輸出的extra列來判斷,對於一個索引覆蓋查詢,顯示為using index,MySQL查詢優化器在執行查詢前會決定是否有索引覆蓋查詢。
注意:覆蓋索引也並不適用於任意的索引型別,索引必須儲存列的值。Hash和full-text索引不儲存值,因此MySQL只能使用B-TREE。並且不同的儲存引擎實現覆蓋索引都是不同的。並不是所有的儲存引擎都支援它們。如果要使用覆蓋索引。一定要注意SELECT 列表值取出需要的列。不可以是SELECT * ,因為如果將所有欄位一起做索引會導致索引檔案過大。查詢效能下降。不能為了利用覆蓋索引而這麼做。

21.只需要讀取索引而不用讀取資料有以下一些優點:

(1)索引項通常比記錄要小,所以MySQL訪問更少的資料;
(2)索引都按值的大小順序儲存,相對於隨機訪問記錄,需要更少的I/O;
(3)大多資料引擎能更好的快取索引。比如MyISAM只快取索引。
(4)覆蓋索引對於InnoDB表尤其有用,因為InnoDB使用聚集索引組織資料,如果二級索引中包含查詢所需的資料,就不再需要在聚集索引中查找了。

22.區別

Innodb中,索引存貯的是資料本身,可以在需要查詢的列都在索引中存在,則不需要進行資料的查詢,直接查詢索引就獲得了資料
myisam中,索引主要是快取索引。count(*)在該儲存引擎中是覆蓋索引,但是如果count(其他欄位)則不是。

23.全索引掃描並不一定就比全表掃描好,取決於資料儲存位置。如果資料在記憶體,那麼這兩種沒有太大區別。如果資料在磁碟,全表掃描比全索引掃描要好,這是因為,全表掃描是順序讀資料,sequential read,是順序IO。而全索引掃描,可能會產生隨機讀(reandom read),隨機IO,顯然,順序讀要比隨機讀快很多。