索引型別
從資料結構角度:
- B+樹索引,
- hash索引,基於雜湊表實現,只有全值匹配才有效。以連結串列的形式解決衝突。查詢速度非常快 O(1)
- 全文索引,查詢的是文字中的關鍵詞,而不是直接比較索引中的值,類似於搜尋引擎做的事情。
- 空間資料索引(R-Tree),MyISAM支援空間索引,可以用作地理資料儲存,會從所有維度來索引資料,有效的使用任意維度來組合查詢。
從物理儲存角度:
-
聚簇索引,InnoDB同一個結構儲存了索引和資料行,葉子節點的data域存放了行的全部資料。
優點:資料訪問快。將索引和資料儲存在同一個B+樹種,因此比非聚簇索引快。可以把相關資料儲存到一起。例如根據使用者ID來聚集資料,只需從磁碟讀取少量資料頁就可以獲得使用者ID的全部郵件。
缺點:插入速度驗證依賴於插入順序,亂序寫入會導致頻繁的頁分裂移動大量資料。更新代價很高,因為要將每個被更新的行移到到新位置。面臨頁分裂問題,當某個頁已滿時,儲存引擎會講該頁分成兩個頁面來容納該行。
儘可能的按主鍵順序插入資料,並且儘可能的使用單調增加的聚簇鍵的值來插入新行。
-
非聚簇索引,MyISAM索引檔案和資料檔案是分離的,葉子節點的data域存放的是行資料的地址
優點: 更新代價比聚集索引要小 。
缺點:跟聚集索引一樣,非聚集索引也依賴於有序的資料。可能會二次查詢(回表) ,當查到索引對應的指標或主鍵後,可能還需要根據指標或主鍵再到資料檔案或表中查詢。
從邏輯角度:
- 普通 /單列索引,普通索引的唯一作用就是為了快速查詢資料,一張表允許建立多個普通索引,並允許資料重複和NULL。
INDEX index_name ( column )
。 - 唯一索引,唯一索引也是一種約束。唯一索引的屬性列不能出現重複的資料,但是允許資料為NULL,一張表允許建立多個唯一索引。
UNIQUE ( column )
- 主鍵索引,資料表的主鍵列使用的就是主鍵索引
PRIMARY KEY ( column)
- 聯合索引,指多個欄位上建立的索引
INDEX index_name ( column1, ... )
,使用時最左匹配原則 - 字首索引,索引字串的一部分
INDEX index_name ( column(10) )
- 全文索引,查詢的是文字中的關鍵詞,而不是直接比較索引中的值,類似於搜尋引擎做的事情。
FULLTEXT ( column)
從表現形式角度:
- 主鍵索引,資料表的主鍵列使用的就是主鍵索引。InnoDB中,當沒有顯式的指定表的主鍵時,InnoDB會自動先檢查表中是否有唯一索引的欄位,如果有,則選擇該欄位為預設的主鍵,否則InnoDB將會自動建立一個6Byte的自增主鍵。
- 二級 / 輔助索引,除開主鍵索引之外的都叫二級索引。在MyISAM中二級索引和主鍵索引的結構大致相同。在InnoDB中二級索引的葉子節點儲存的是主鍵值,通過主鍵值定位行資料,需要兩次索引查詢。使用主鍵值當做指標會讓二級索引佔更多的空間,但是移動行時無需更新二級索引。
- 覆蓋索引,如果一個索引包含(或者說覆蓋)所有需要查詢的欄位的值,我們就稱之為“覆蓋索引”。覆蓋索引即需要查詢的欄位正好是索引的欄位,那麼直接根據該索引,就可以查到資料了, 而無需回表查詢。
索引優化SQL排查調優
- 開啟慢查詢日誌,檢視慢查詢
- 首先線上下環境explain看一下執行計劃,是否符合預期,例如檢視①key欄位是否使用到索引,使用到什麼索引。②type欄位是否為ALL全表掃描。③row欄位掃描的行數是否過大,估計值。MySQL資料單位都是頁,使用取樣統計方法。④extra欄位是否需要額外排序,就是不能通過索引順序達到排序效果;是否需要使用臨時表等。⑤如果是組合索引的話通過key_len欄位判斷是否被完全使用。
- 瞭解業務場景。看業務怎麼使用這個sql,做針對性優化。
- 排除快取的干擾。如果執行緒RT(響應時間)快時慢的話就可能是快取的問題,因為對錶進行更新的話先關快取都會失效
- 使用覆蓋索引。一個索引包含所有需要查詢的欄位的值。直接根據該索引就可以查到資料,無需回表查詢。比如InnoDB二級索引包含主鍵值,通過二級索引查詢主鍵值就會用到覆蓋索引,無需回表
- 使用組合索引。比如根據名稱查庫存就可以建立聯合索引,不需要根據名稱查出主鍵之後在查庫存了,但需要考慮業務場景,避免佔據較大空間。
- 注意最左字首原則,按照定義的順序寫sql。如果一個模糊查詢只使用到一個組合索引的最左索引,那這樣還是能用到這個聯合索引,並不需要新建一個單獨的索引。
- 選擇合適的索引列順序。當不需要考慮排序和分組時,將選擇性最高的列放到索引的最前列通常是很好的。
- 索引下推,mysql5.6之後官方自動優化。比如聯合索引(name,age),根據name的like查詢並且age在一定區間內查詢所有匹配的行資料時,就只有name可以用到索引,age並不會。在優化後,name用到索引之後,會直接再從索引中匹配滿足條件的age,之後再回表查詢,這樣需要回表查詢的資料就相比減少了。其實就是充分利用了索引中的資料,儘量在查詢出整行資料之前過濾掉無效的資料。
- 使用字首索引。當要給字串加索引時,可以使用字首索引,節省資源佔用。如果字首區分度不高可以倒序儲存或者是儲存hash。
- 注意隱式型別轉換。比如id是字元型別,查詢的使用使用int型別會相當於加了型別轉換函式,用不上索引。兩個表的字符集不一樣也會導致,例如utf8mb4(可以超過3位元組)和utf8(最多3位元組)
- 被頻繁更新的欄位應該慎重建立索引,不被經常查詢的欄位沒有必要建立索引。
- 遵循索引設計準則三星索引,但一般難以滿足,需要依賴實際成本和業務場景。① WHERE 後面參與查詢的列可以組成了單列索引或聯合索引。② 避免排序,即如果 SQL 語句中出現 order by colulmn,那麼取出的結果集就已經是按照 column 排序好的,不需要再生成臨時表。③儘量使用覆蓋索引
- 注意索引失效場景。