雖然 InnoDB 也使用 B+Tree 作爲索引結構,但具體實現方式卻與 MyISAM 截然不同。InnoDB 的數據文件本身就是索引文件。MyISAM 索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。
而在InnoDB 中,表數據文件本身就是按 B+Tree 組織的一個索引結構,這棵樹的葉子節點保存了完整的數據記錄。這個索引的 key 是數據表的主鍵,因此 InnoDB 表數據文件本身就是主索引。
上圖是 InnoDB 主索引(同時也是數據文件)的示意圖,可以看到葉節點包含了完整的數據記錄。這種索引叫做聚集索引。因爲 InnoDB 的數據文件本身要按主鍵聚集,
1 .InnoDB 要求表必須有主鍵,如果沒有顯式指定,則 MySQL系統會自動選擇一個可以唯一標識數據記錄的列作爲主鍵,如果不存在這種列,則MySQL 自動爲 InnoDB 表生成一個隱含字段作爲主鍵,類型爲長整形。
同時,請儘量在 InnoDB 上採用自增字段做表的主鍵。因爲 InnoDB 數據文件本身是一棵B+Tree,非單調的主鍵會造成在插入新記錄時數據文件爲了維持 B+Tree 的特性而頻繁的分裂調整,十分低效,而使用自增字段作爲主鍵則是一個很好的選擇。如果表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁。如下圖所示:
這樣就會形成一個緊湊的索引結構,近似順序填滿。由於每次插入時也不需要移動已有數據,因此效率很高,也不會增加很多開銷在維護索引上。
2.第二個與 MyISAM 索引的不同是 InnoDB 的輔助索引 data 域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB 的所有輔助索引都引用主鍵作爲 data 域。
例如,圖 11 爲定義在 Col3 上的一個輔助索引:
聚集索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然後用主鍵到主索引中檢索獲得記錄。
引申:爲什麼不建議使用過長的字段作爲主鍵?
因爲所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。
聚簇索引與非聚簇索引
InnoDB 使用的是聚簇索引, 將主鍵組織到一棵 B+樹中, 而行數據就儲存在葉子節點上, 若使用"where id = 14"這樣的條件查找主鍵, 則按照 B+樹的檢索算法即可查找到對應的葉節點, 之後獲得行數據。 若對 Name 列進行條件搜索, 則需要兩個步驟:
第一步在輔助索引 B+樹中檢索 Name, 到達其葉子節點獲取對應的主鍵。
第二步使用主鍵在主索引 B+樹種再執行一次 B+樹檢索操作, 最終到達葉子節點即可獲取整行數據。
MyISM 使用的是非聚簇索引, 非聚簇索引的兩棵 B+樹看上去沒什麼不同, 節點
的結構完全一致只是存儲的內容不同而已, 主鍵索引 B+樹的節點存儲了主鍵, 輔助鍵索引B+樹存儲了輔助鍵。 表數據存儲在獨立的地方, 這兩顆 B+樹的葉子節點都使用一個地址指向真正的表數據, 對於表數據來說, 這兩個鍵沒有任何差別。 由於索引樹是獨立的, 通過輔助鍵檢索無需訪問主鍵的索引樹。
爲了更形象說明這兩種索引的區別, 我們假想一個表如下圖存儲了 4 行數據。 其中Id 作爲主索引, Name 作爲輔助索引。 圖示清晰的顯示了聚簇索引和非聚簇索引的差異
聯合索引及最左原則
聯合索引存儲數據結構圖:
最左原則:
例如聯合索引有三個索引字段(A,B,C)
查詢條件:
(A,,)---會使用索引
(A,B,)---會使用索引
(A,B,C)---會使用索引
(,B,C)---不會使用索引
(,,C)---不會使用索引