Mysql 索引原理及優化
什么是索引
為什么需要索引?
- 索引是數據表種一個或者多個列進行排序的數據結構
- 索引能夠大幅提升檢索速度
- 創建、更新索引本身也會耗費空間和時間
查找結構進化史
- 線性查找:一個個找;實現簡單;太慢
- 二分查找:有序;簡單;要求是有序的,插入特別慢
- HASH查找:查詢快;占用空間;不太適合存儲大規模數據
- 二叉查找樹:插入和查詢很快(log(n));無法存大規模數據,復雜度退化
- 平衡樹:解決 BST 退化問題,樹是平衡的;節點非常多的時候,依然樹高很高
- 多路查找樹:一個父親多個孩子節點(度);節點過多樹高不會特別深
- 多路平衡查找樹:B-Tree
關於這些查找結果的演示推薦:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
這個網站關於數據結構的演示很直觀,我們可以通過其中的動畫來學習。
比如二叉查找樹退化問題:
可以明顯看到,由於我們輸入的數字是順序增長的,二叉查找樹變成了單邊增長的線性結構,這就是復雜度退化。
平衡樹(AVL)則沒有這個問題:
什么是 B-Tree?
- 多路平衡查找樹(每個節點最多 m(m>=2) 個孩子,稱為 m 階或者度)
- 葉節點具有相同的深度
- 節點的數據 key 從左到右是遞增的
演示
B+Tree
- Mysql 實際使用的 B+Tree 作為索引的數據結構
- 只在葉子節點帶有指向記錄的指針(For what?可以增加樹的度)
- 葉子節點通過指針相連(For what?實現范圍查詢)
Mysql 創建索引類型
- 普通類型(CREATE INDEX)
- 唯一索引,索引列的值必須唯一(CREATE UNIQUE INDEX)
- 多列索引
- 主鍵索引(PRIMARY KEY),一個表只能有一個
- 全文索引(FULLTEXT INDEX),InnoDB 不支持
什么時候創建索引
- 經常用作查詢條件的字段
- 經常用作表連接的字段
- 經常出現在 order by,group by 之后的字段
創建索引有哪些需要注意的?
最佳實踐
- 非空字段 NOT NULL,Mysql 很難對空值作查詢優化
- 區分度高,離散度大,作為索引的字段值盡量不要有大量相同值
- 索引的長度不要太長(比較耗費時間)
索引什么時候失效?
模糊匹配、類型隱轉、最左匹配
- 以 % 開頭的 LIKE 語法,模糊搜索
- 出現隱式類型轉換(在 Python 這種動態語言查詢中需要注意)
- 沒有滿足最左前綴原則
什么是聚集索引和非聚集索引?
- 聚集還是非聚集指的是 B+Tree 葉節點存的是指針還是數據記錄
- MyISAM 索引和數據分離,使用的是非聚集索引
- InnoDB 數據文件就是索引文件,主鍵索引就是聚集索引
對比如下
區別是在 B+Tree 的葉節點存儲數據還是指針
MyISAM 索引是非聚集的,InnoDB 主鍵索引是聚集索引
輔助索引
還有一個輔助索引,我們也可以了解下。
如何排查慢查詢
慢查詢通常是缺少索引,索引不合理或者業務代碼實現所致
slow_query_log_file
開啟並且查詢慢查詢日志- 通過
explain
排查索引問題 - 調整數據修改索引;業務代碼層限制不合理訪問