MySql索引總結

MySQL 索引底層數據結構

  Mysql索引使用的數據結構主要有 BTree索引Hash索引。對於Hash索引來講,底層數據結構就是哈希表,所以在絕大多數需求爲單條記錄查詢的時候,使用Hash索引查詢性能最快。其他大多數場景建議使用BTree索引。html

爲何索引可以提升查詢速度

  MySQL的基本存儲結構爲 ,頁與頁之間使用雙向鏈表進行連接,頁內記錄使用單向鏈表進行連接。查詢數據時,先使用雙向鏈表查詢到數據所在的頁,頁內查詢時,where子句中若是是主鍵則根據二分查找進行查詢,若是爲非主鍵則使用遍歷鏈表的方式進行查詢。整個時間複雜度爲O(n)。面試

  使用索引以後,能夠利用BTree的數據結構進行查找數據,時間複雜度能夠作到O(log n)。sql

使用索引的缺點

  • 建立索引和維護索引須要耗費時間,這種時間隨着數據量的增長而增長。
  • 索引須要佔用物理空間,數據量越大,佔用的空間越大。
  • 在進行增刪改的過程當中,因爲須要維護索引,所以會下降效率,對於增刪改操做比較多的表,不適合創建太多索引。

MySQL索引類型

  1. 主鍵索引:特殊的索引,惟一的標識一條記錄,不能爲空,通常用primary key來約束。
    ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 
    複製代碼
  2. 惟一索引:索引列的值必須惟一,且不能爲空,若是是組合索引,則列值的組合必須惟一。
    ALTER TABLE `table_name` ADD UNIQUE ( `column` ) 
    複製代碼
  3. 普通索引:最基本的索引,它沒有任何限制。
    ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
    複製代碼
  4. 全文索引:全文索引(FULLTEXT)僅能夠適用於MyISAM引擎的數據表;做用於CHAR、VARCHAR、TEXT數據類型的列。
    ALTER TABLE `table_name` ADD FULLTEXT ( `column`) 
    複製代碼
  5. 聯合索引:將幾個列做爲一條索引進行檢索,使用最左匹配原則。
    ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
    複製代碼

聯合索引的最左匹配原則

簡單來說,創建聯合索引時,當最左邊的一個或多個索引肯定以後,緊跟着的索引纔是有序的。(以下圖,創建a,b的聯合索引後,a的值爲[1,1,2,2,3,3]有序,b的值爲[1,2,1,4,1,2])當不肯定a的值時,b的值在結構上是無序的,這時僅where子查詢中若是隻使用b進行查找則會全表查找。 因此當咱們用 where a = 1 and b = 2 進行查詢時,因爲a肯定以後b的值有序,因此b字段查詢時使用上索引。當咱們用 where a > 1 and b = 2 進行查詢時,a字段可使用索引,但b字段因爲無序因此沒法使用索引。數據庫

join index

  • 總結
  • 最左前綴匹配原則。MySQL會一直向右匹配直到遇到範圍查詢(>,<,BETWEEN,LIKE)就中止匹配,好比: a = 1 AND b = 2 AND c > 3 AND d = 4,若是創建 (a,b,c,d)順序的索引,d是用不到索引的,若是創建(a,b,d,c)的索引,則均可以用到,a,b,d的順序能夠任意調整。
  • 等於(=)和in 能夠亂序。好比,a = 1 AND b = 2 AND c = 3 創建(a,b,c)索引能夠任意順序,MySQL的查詢優化器會幫你優化成索引能夠識別的模式

彙集索引和非彙集索引

簡單歸納數據結構

  • 彙集索引就是以主鍵建立的索引
  • 非彙集索引就是以非主鍵建立的索引

兩者區別post

  • 彙集索引中,葉子節點存儲的是表中的數據
  • 非彙集索引中,葉子節點存儲的是主鍵和索引列
  • 使用非彙集索引查詢出數據時,拿到葉子上的主鍵再去查到想要查找的數據。(拿到主鍵再查找這個過程叫作回表)
  • 建立多個非彙集索引,每一個彙集索引會生成一個索引樹,所以創建多個索引會佔用更多的磁盤空間。

索引和查詢優化的注意事項

  • 前導的模糊查詢沒法使用索引,如 where like '%索引' 沒法使用索引
  • Union、in、or能夠命中索引,建議使用in
  • 負條件查詢不能使用索引,能夠優化爲in查詢,其中負條件有!=、<>、not in、not exists、not like等
  • 創建聯合查詢時,區分度最高的字段在最左邊
  • 把計算放到業務層而不是數據庫層,由於在字段上計算不能命中索引
  • 強制類型轉換會全表掃描,若是phone字段是varcher類型,則下面的SQL不能命中索引。Select * fromuser where phone=13800001234
  • 創建索引的列不能爲null,使用not null約束及默認值
  • 若是明確知道查詢結果只要一條,limit 1可以提升效率,好比驗證登陸的時候
  • 使用合理的分頁提升效率。select id,name from product limit 866613, 20使用上述SQL語句作分頁的時候,可能有人會發現,隨着表數據量的增長,直接使用limit分頁查詢會愈來愈慢。優化的方法以下:能夠取前一頁的最大行數的id,而後根據這個最大的id來限制下一頁的起點。好比此列中,上一頁最大的id是866612。SQL能夠採用以下的寫法:select id,name from product where id> 866612 limit 20。

面試經歷

Q:請說說索引的注意事項,或者說說索引的優缺點。性能

參考資料:

相關文章
相關標籤/搜索