MySql的索引分類、資料結構以及優化細節
文章目錄
實操案例: 選錯「索引」導致的線上慢查詢
explain指令:MySQL Explain詳解B樹和B+樹各自的優勢:為什麼 Mongodb 索引用 B 樹,而 Mysql 用 B+ 樹?
索引的分類
- 主鍵索引(不允許空值)
- 唯一索引(允許空值)
- 普通索引(其他普通列)
- 全文索引(關鍵字查詢,mysql不推薦用)
- 組合索引(一個索引包含多個列)
mysql資料結構
-
樹形結構的演化
二叉樹->BST(banary search tree,實現了二分查詢,但是插入遞增資料的話,會退化成近似連結串列的結構)->AVL Tree -
mysql為什麼不使用以上樹形結構
- IO讀取資料的最小單位是頁(8K/16K等),每個節點上的資料不能保證對齊;
- 資料量大的時候,樹型結構變深,增加IO次數,降低效率。
-
B-Tree
-
b樹有個概念叫degree,可以定義每個節點儲存的資料量(多個數據可以存放進一個節點,可以作為一個數據頁)。
-
b樹模型(InnoDB預設載入16K)
-
-
B+樹模型(非葉子節點全部存放指標和索引,資料全部放進葉子結點,減小了樹的深度,提高查詢效率),三層B+樹可以支撐千萬級別的資料量
-
B+樹所有的葉子結點之間存在雙向連結串列。
- InnoDB–B+Tree,葉子結點直接存放資料
- 每建一個索引,就會有一顆B+樹,換言之,一張表裡可以有多棵樹,但是帶有原始資料的tree只有一顆(如下例子,name列也建立了索引,name樹葉子節點存放的就是主鍵id的值)。
面試常問名詞
- 回表:先查name樹查到id值,再查id樹找到資料,這樣查多棵樹的行為叫做回表,應該儘量避免。
- 索引覆蓋:查詢的索引資訊包含查詢資料,不需要回表即可返回資料,稱為索引覆蓋。
select id,name from tbl where name=‘zhang’;
select * from tbl where name=‘zhang’;此兩種方式查詢過程不一樣。
- 最左匹配:針對於組合索引,優先過濾不符合最左定義的索引的資料。
name age 組合索引
where name = ? and age = ?
where name = ?
where age = ?
where age = ? and name = ? 依然會走最左匹配,優化器優化
- 索引下推:針對於組合索引,5.6之後根據name,age兩個列的值去獲取資料,直接返回(減少了整體io量)。
Mysql優化小細節
-
當使用索引列進行查詢的時候,儘量不要使用表示式,把計算放在業務層而不是資料庫層;
-
儘量使用主鍵查詢,而不是其他索引,因為主鍵查詢不會觸發回表查詢(主鍵最好自增,否則不好維護,大小亂序會造成葉子結點分裂);
-
使用索引的選擇性。如果主鍵是varchar且較長(uuid),可以使用left(uid,7)來建立索引。
-
強制型別轉化,會使索引失效,進行全盤掃描。
-
更新十分頻繁,資料區分度不高的欄位不宜建立索引。
-
索引列不允許為null(mybatis會把0當做null);
-
表連線查詢最好不要超過三張表;
-
能使用limit儘量使用limit,減少IO量;
-
建立索引應避免以下認知:
- 索引越多越好
- 過早優化,在不瞭解系統的情況下進行優化