Mysql 常見面試題
1.索引
1.什麼是索引?
索引是對數據庫中一個或者多個值進行排序的數據結構,以便實現快速查詢
2.Mysql索引是如何實現的?
mysql索引使用的是B+樹,主要是查詢效率高,時間複雜度是O(log N),可以充分利用磁盤預讀的特性,樹可以有多個孩子節點,並且樹深度很小,葉子節點有序且存儲數據
3.爲什麼選擇B+樹作爲索引結構?
- hash索引:hash索引的底層是哈希表,因爲hash表是存儲key和value鍵值對的,所以區間查詢無法通過hash索引實現,需要做全表掃描,所以hash索引只適用於等值查詢的場景,而B+樹是一種多路平衡查找樹,節點是天然有序的(左孩子小於父節點,右孩子大於父節點),對於範圍查詢的時候不需要做全表掃描
- 二叉查找樹:解決了排序的基本問題,但是無法保證平衡,可能會退化爲鏈表
- 平衡二叉樹:通過旋轉操作解決了平衡問題,但是旋轉操作效率太低
- 紅黑樹:通過捨棄嚴格的平衡和引入紅黑節點,解決了平衡二叉樹旋轉效率太低的問題,但在磁盤的場景下,樹的高度還是太高了,IO次數太多
- B樹:非葉子節點會存儲數據,內存佔用較高
- B+樹:在B樹的基礎上,將非葉節點改造爲不存儲數據的純索引節點,進一步降低了樹的高度,此外,將葉節點使用指針連接成鏈表,範圍查詢更加高效
4.mysql爲什麼加了索引可以加快查詢?
因爲使用索引後可以不用掃描整個表來定位某行數據,可以先通過索引表找到改行對應的物理地址然後訪問相應數據
5.索引的優點和缺點
優點:
- 可以加快檢索數據的速度,減少IO次數
- 可以加快數據的分組與排序操作
- 可以加速表和表之間的連接,因爲掃描整個表的索引消耗的時間遠遠比掃描整個表的時間要少
缺點:
- 空間方面:索引本身也是表,會佔用存儲空間,索引佔用的空間是數據表的1.5倍
- 時間方面:創建和維護索引都需要時間,數據量越多,消耗的時間也越多,對數據進行增刪改查都需要動態維護索引
6.mysq的索引主要有哪些?
- 唯一索引:不允許出現相同的值,可以是NULL
- 普通索引:允許出現相同值
- 主鍵索引:不允許出現相同值,不可以是NULL
- 全文索引:針對值中的某個單詞查詢,解決海量數據模糊查詢的問題
- 組合索引:實際上是將多個字段建到一個索引裏,列值的組合必須唯一
7.使用組合索引有什麼好處?
- 空間開銷更小:建立一個N字段的組合索引,功能相當於建立了N個索引,但開銷會小很多
- 覆蓋索引:這樣有些查詢僅通過索引就能獲得結果,不必再從表中獲取,稱之爲實現了索引覆蓋,是提升性能的優化手段之一
- 效率更高:索引列越多,通過索引篩選出數據更快
8.mysql組合索引最左匹配原則
最左匹配原則:即最左優先,在檢索數據時,從組合索引的最左邊開始匹配,然後一直向右匹配,直到遇到範圍查詢(即<,>,between,like)就停止匹配
比如a=3 and b=4 and c>5 and d=6,abcd建立組合索引,d就用不到索引了,因爲c>5是範圍查詢,根據最左匹配原則,在c時就停止匹配所以d就用不到索引了
9.什麼叫做索引失效?什麼情況下會失效?如何判斷是否失效?
索引失效:檢索時因爲某些特別操作導致用不上索引,稱之爲索引失效
什麼情況下索引會失效?
-
對索引字段做任何計算,函數操作
-
SELECT * FROM user WHERE age = age+1
-
-
對索引列做範圍性操作,比如>,<,!=
-
使用like通配符,並且%在數據左側時,注意,%在數據右側時索引並不會失效
-
SELECT * FROM user WHERE name like "%小"
-
-
查詢中存在類型轉換時
-
違法最左前綴法則時
-
where對null判斷
-
or操作至少有一個字段沒有索引
判斷索引是否失效:explain命令執行sql語句,type爲all代表失效
-
失效:
-
有效:
7.聚集索引和非聚集索引的區別?
-
聚集索引:決定表中數據的物理順序,邏輯順序和物理順序是一樣的,一張表只能有一個,聚集索引對範圍查找特別有效,因爲其數據是物理相鄰的,可以加快範圍查找的速度
-
非聚集索引:決定表中數據的邏輯順序,但和其記錄的物理順序不一定一致
聚集索引的葉子節點是數據節點,非聚集索引的葉子節點仍是索引節點,通過一個指針再指向數據塊
8.什麼字段適合創建索引?
- 經常做查詢的字段
- 經常做表連接的字段
- 經常需要排序,分組或過濾的字段,即出現在order by,group by,discinct
2.事務
1.什麼叫事務?
一系列操作的集合,要麼都執行,要麼都不執行
2.事務有什麼特性?
ACID特性
- 原子性:事務是一個原子的操作單元,其對數據的修改,要麼全都執行,要麼全都不執行
- 一致性:事物把系統從一個一致狀態轉變爲另外一個一致狀態,即事物完成後,所有數據必須符合業務規範
- 隔離性:多個事物併發執行時,一個事物的執行不應該影響其他事物的執行,即事物以相互隔離的方式執行,事物以外的實體無法知道事物過程的中間狀態,防止數據損壞
- 持久性:事物提交以後,事物必須以一種持久性方式存儲起來,一旦事物完成,無論發生什麼系統錯誤,它的結果都不應該受到影響,這樣就能從任何系統崩潰中恢復過來,通常情況下,事物結果被寫到持久化存儲器中
3.事務隔離的級別有哪幾種?
隔離級別:一個session中的事務可能對另一個session中的事務的影響
總共有四個隔離級別
- 讀未提交:一個事務可以讀取其他事務未提交的數據,最低級別,存在髒讀問題
- 讀已提交:一個事務要等另一個事務提交後才能讀取數據,可避免髒讀的發生,但不能避免不可重複讀問題
- 可重複讀:在開始讀取數據(事務開啓)時,不再允許修改操作,可避免髒讀、不可重複讀問題,但不能避免幻讀問題
- 串行:事務串行執行,可避免髒讀,不可重複讀,幻讀,但效率比較低
mysql的默認隔離級別是可重複讀,隔離級別越高,併發越低
4.事務的併發可能會出現什麼問題?
- 丟失更新:A事務的更新覆蓋了B事務的更新
- 髒讀:A事務讀取了B事務寫但未提交的數據
- 不可重複讀:同樣條件下兩次讀取結果不同,也就是兩次讀取期間,數據被其他事務篡改了
- 幻讀:同樣條件下讀取出的記錄數量不一樣,新增或減少了一些記錄
5.如何解決幻讀問題?
- 方法1:將事務的隔離級別設置成串化,但效率太低
- 方法2:通過next-key lock
- 即在當前讀事務開啓時,給涉及到的行加寫鎖,防止寫操作,給涉及到的行兩端加Gap lock間隙鎖防止新增的行寫入
- 但是next-key lock在併發情況下經常造成死鎖問題,死鎖的檢測和處理也會花費時間,一定程度上影響併發量
實際上很多項目實際上不會用到上面兩種方法,串化性能差,有的時候其實幻讀問題是可以接受的