mysql 索引十連問| 劍指 offer - mysql

如下是結合網上及此前面試時遇到的一些關於mysql索引的面試題。
若對mysql索引不太瞭解可先翻閱相關文章mysql

主鍵索引和非主鍵索引有什麼區別?

主鍵索引樹中葉子節點存儲的是整行數據,而非主鍵索引葉子節點上保存的是主鍵的值。使用非主鍵索引時,先從非主鍵索引獲取到行對應主鍵ID,以後再根據id在主鍵索引樹上搜索對應行數據,這個過程也被稱爲回表。數據庫

通常使用什麼字段做爲主鍵,爲何?

通常使用innodb的自增整數類型做爲主鍵:數組

  • 由於自增,容易保證主鍵索引的有序性,同時還能避免新數據中間位置插入時致使的頁分裂;
  • 二級索引葉子節點上保存的是主鍵值,整數類型主鍵長度較小,二級索引樹佔用的空間較小。

索引使用場景

where

爲查詢條件字段建立索引,以達到快速過濾指定條件數據的目的。數據結構

## order by
當使用order by將查詢結果按某個字段排序時,可考慮爲該字段建立索引。沒有索引時,會先將查詢結果放到內存中進行排序(若內存空間不足,會利用磁盤輔助排序),比較影響查詢效率。
索引自己是有序的,能夠直接按索引的順序逐條回表取出數據便可。若是是分頁查詢,效果更好,這時候只須要取出某個範圍的索引對應的數據,而不須要取出全部知足條件的數據排序後再截取返回分頁數據。函數

join

使用join時,爲被驅動表的關聯字段建立索引,能夠有效提升查詢效率。好比select * from t1 straight_join t2 on (t1.a=t2.a) where t1.b = 'xxxx'; t2的字段a上有索引,查詢過程會是先從表1中依次取出知足條件的行數據,以後用行數據中的a字段去t2上匹配後將兩表字段拼接返回,此時能使用到t2.a的索引,避免了t2全表掃描。性能

索引覆蓋

若是select字段+where字段字段列數不太多且查詢頻繁時,能夠考慮爲select和where字段建立聯合索引,避免查詢時回表,提升查詢效率。好比select a from t where b = ‘xx’, 建立聯合索引(b, a), 此時掃描索引樹後,就已經獲得須要查詢的字段a了,不須要再回表。須要注意的是聯合索引字段的順序,這個語句沒法使用到索引(a, b)。mysql索引

建立索引須要注意的地方

  • 最左前綴匹配原則,聯合索引須要注意索引字段的順序,mysql 會一直向右匹配直到遇到範圍查詢 (>、<、between、like) 就中止匹配,好比 a = 1 and b = 2 and c > 3 and d = 4 ,若是創建 (a,b,c,d) 順序的索引,d 是用不到索引的。
    字段是否用到索引的意思是字段是否能利用字段在索引中的有序性進行快速過濾。索引(a,b,c,d), 在索引樹上是先按a進行排序,再按b進行排序,以此類推,排序規則相似order by a,b,c,d。上面查詢條件中,a定值,b是有序的;b定值,c是有序的;c範圍查詢,剩下的d是無序的。因此d沒法使用到該索引。
  • 基數小,區分度低的不適合建立索引。好比性別,最多基數最多總共就3個,此時索引過濾性能不高,查完索引後還需回表,可能比直接全表掃描效率更低。
  • 更新頻繁的字段建立索引時要權衡索引維護成本。
  • 儘可能擴展索引,好比已經有a索引,如今要加 (a,b) 的索引,那麼只須要修改原來的索引便可。
  • 避免對text大字段建立索引,會致使索引樹太大,查詢效率不高。若是大字段前n個字符區分度較高,能夠考慮建立前綴索引,只索引開始的部分字符,這樣能夠節約索引空間,提升索引效率。其缺點是不能用於ORDER BY和GROUP BY操做,也不能用於覆蓋索引(由於前綴索引樹上只有字段的部份內容,須要進行回表)。

何時索引會失效?

  • 模糊查詢時查詢條件以」%」開頭沒法使用到索引
  • 使用or查詢時,只有當全部的查詢條件字段都有索引才能使用到,好比a=1 or b = 2,只有當a和b都有索引才能使用到索引。
  • 數據類型出現隱式轉換,如varchar不加單引號的時候可能會自動轉換爲int類型,這個時候索引失效。
  • 在索引列上使用IS NULL或者 IS NOT NULL 時候,索引失效,由於索引不會索引空值。
  • 在索引字段上使用」NOT、 <>、!=、NOT IN 「時是不會使用索引的,這時只會進行全表掃描。
  • 對索引字段進行計算操做,函數操做時不會使用索引。
  • 當優化器以爲全表掃描速度比索引速度快的時候不會使用索引。通常出如今全表數據比較少的狀況下,這時全表掃描比在非主鍵索引上查找後再回錶速度可能更快。
  • 聯合索引時,查找不知足最左匹配規則,沒法使用到聯合索引。

innodb使用b+樹做爲索引模型的緣由

Mysql設計的使用場景比較普遍,須要對遍歷查詢、單條查詢、數據更新都須要較好的性能支持。B+樹的特性是隻在葉子節點上存儲數據。能夠從數據讀寫方面與哈希表、有序數組、b樹其餘幾種索引模型進行比較:學習

  • 哈希表:哈希表只能進行等值查詢,在處理範圍查詢和排序查詢時,須要全表掃描哈希表。
  • 有序數組:有序數組在進行數據更新時成本較大。往數組中間位置添加數據時,須要移動後面的數據位置。
  • B樹:b樹在非葉子節點上也存儲數據,在遍歷數據時,須要對不一樣層級的節點上的數據進行拼接和排序,這會致使屢次磁盤io。查詢效率較低。

如何刪除百萬級別或以上的數據?

能夠考慮先刪掉表的索引,等刪除數據後再重建索引。當咱們在進行數據修改時,須要同時修改索引,這些額外的索引維護成本較低數據修改的效率;同時,大量的數據刪除會致使索引數據頁產生大量的碎片空間,此時刪除數據後重建索引可使索引樹更「緊湊」,提升磁盤空間利用率。

Innodb中的B+樹模型中,N叉樹的N可否被修改?

  1. 經過調整索引字段大小來修改
    N 叉樹中非葉子節點存放的是索引信息,索引包含 Key 和 Point 指針。Point 指針固定爲 6 個字節,假如 Key 爲 10 個字節,那麼單個索引就是 16 個字節。若是 B + 樹中頁大小爲 16 K,那麼一個頁就能夠存儲 1024 個索引,此時 N 就等於 1024。咱們經過改變 Key 的大小,就能夠改變 N 的值。
  2. 經過修改頁大小間接修改,頁越大,每頁存放的索引數量就越多,N就越大。

數據頁調整後,若是數據頁過小層數會太深,數據頁太大,加載到內存的時間和單個數據頁查詢時間會提升,須要達到平衡才行。

如何知道語句有沒有走索引查詢?

能夠利用 explain 查看 sql 語句的執行計劃,經過執行計劃來分析索引使用狀況。

寫在最後

喜歡本文的朋友,歡迎關注公衆號「會玩 code」,專一大白話分享實用技術。
image.png

公衆號福利

回覆【mysql】獲取免費測試數據庫!!
回覆【pdf】獲取持續更新海量學習資料!!

相關文章
相關標籤/搜索