MySQL數(shù)據(jù)庫索引及底層數(shù)據(jù)結(jié)構(gòu)詳解
MySQL默認使用的索引底層數(shù)據(jù)結(jié)構(gòu)是B+樹,默認存儲引擎是InnoDB引擎。
這是MySQL文檔,有需要的自己瀏覽。
接下來我們步入今天的正題:
1. 什么是索引
- 索引(index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)(有序)。可以快速定位數(shù)據(jù)位置而不必掃描整個表。
- 在數(shù)據(jù)之外,數(shù)據(jù)庫系統(tǒng)還維護著滿足特定査找算法的數(shù)據(jù)結(jié)構(gòu)(B+樹),這些數(shù)據(jù)結(jié)構(gòu)以某種方式引用(指向)數(shù)據(jù),這樣就可以在這些數(shù)據(jù)結(jié)構(gòu)上實現(xiàn)高級查找算法這種數(shù)據(jù)結(jié)構(gòu)就是索引。
索引的優(yōu)缺點:
優(yōu)點
- 提高查詢速度:索引可以大大加快數(shù)據(jù)檢索速度,特別是對于大型表
- 加速排序和分組操作:ORDER BY和GROUP BY操作在有索引時會更快
- 優(yōu)化連接操作:表連接時如果有適當?shù)乃饕龝@著提高性能
- 保證數(shù)據(jù)唯一性:唯一索引可以確保列中數(shù)據(jù)的唯一性
- 減少服務(wù)器掃描的數(shù)據(jù)量:MySQL可以使用索引直接定位到所需數(shù)據(jù),而不必掃描整個表
缺點
- 占用額外存儲空間:索引需要額外的磁盤空間
- 降低寫入性能:
- INSERT操作需要同時更新索引
- UPDATE操作如果修改了索引列需要更新索引
- DELETE操作也需要更新索引
- 維護成本:索引需要定期維護,特別是在數(shù)據(jù)頻繁變更的情況下
- 優(yōu)化器可能不使用索引:在某些情況下,MySQL優(yōu)化器可能決定不使用索引
- 索引選擇過多可能導(dǎo)致性能下降:過多的索引會增加優(yōu)化器選擇執(zhí)行計劃的時間
索引的數(shù)據(jù)類型:
MySQL支持多種索引類型,每種類型適用于不同的場景和需求。
1. 普通索引 (INDEX / KEY)
- 最基本的索引類型,沒有特殊限制
- 語法:
CREATE INDEX index_name ON table_name(column_name)
- 適用于大多數(shù)查詢場景
2. 唯一索引 (UNIQUE INDEX)
- 確保索引列的值唯一,但允許NULL值
- 語法:
CREATE UNIQUE INDEX index_name ON table_name(column_name)
- 常用于主鍵或需要唯一約束的列
3. 主鍵索引 (PRIMARY KEY)
- 特殊的唯一索引,不允許NULL值
- 每個表只能有一個主鍵
- 語法:
ALTER TABLE table_name ADD PRIMARY KEY (column_name)
4. 全文索引 (FULLTEXT INDEX)
- 專門用于全文搜索,僅適用于MyISAM和InnoDB(MySQL 5.6+)引擎
- 語法:
CREATE FULLTEXT INDEX index_name ON table_name(column_name)
- 支持MATCH AGAINST操作
5. 組合索引 (復(fù)合索引)
- 在多個列上創(chuàng)建的索引
- 語法:
CREATE INDEX index_name ON table_name(col1, col2, col3)
- 遵循最左前綴原則
6. 空間索引 (SPATIAL INDEX)
- 用于地理空間數(shù)據(jù)類型(GEOMETRY, POINT, LINESTRING, POLYGON等)
- 僅MyISAM表支持
- 語法:
CREATE SPATIAL INDEX index_name ON table_name(column_name)
7. 前綴索引
- 對列值的前N個字符建立索引
- 語法:
CREATE INDEX index_name ON table_name(column_name(N))
- 適用于長字符串列
8. 哈希索引
- Memory存儲引擎默認使用哈希索引
- InnoDB有自適應(yīng)哈希索引功能(自動管理)
- 僅支持等值查詢(=, IN),不支持范圍查詢
9. 覆蓋索引
- 不是一種單獨的索引類型,而是一種使用方式
- 當查詢的所有列都包含在索引中時,MySQL可以直接從索引獲取數(shù)據(jù)而無需回表
注意一點:聚簇索引(Clustered Index)和非聚簇索引(Non-clustered Index)雖然也稱之為索引,但和這些分類有很大的區(qū)別。
核心原因還是因為:分類維度不同
- MySQL官方按功能分類(開發(fā)者視角)
- 這些主鍵索引、唯一索引、普通索引、全文索引等,主要關(guān)注索引的邏輯功能和約束條件
- 聚簇/非聚簇是存儲實現(xiàn)分類(引擎內(nèi)部視角)
- 描述數(shù)據(jù)與索引的物理存儲關(guān)系,屬于底層實現(xiàn)機制而非用戶可配置選項。
未單獨列為類型的其他原因:
- 引擎相關(guān)性:
- 是否聚簇取決于存儲引擎實現(xiàn),比如:InnoDB有聚簇索引,MyISAM則沒有。
- 用戶不可選擇性:
- 開發(fā)者不能直接選擇創(chuàng)建聚簇/非聚簇索引,而是由主鍵定義和引擎特性自動決定。
- 透明性考慮:
- 對大多數(shù)應(yīng)用開發(fā)是底層實現(xiàn)細節(jié),功能分類對開發(fā)者更實用。
- 歷史兼容性:
- 不同引擎行為差異大,統(tǒng)一分類會引發(fā)混淆。
2. 索引的底層數(shù)據(jù)結(jié)構(gòu)
MySQL索引使用多種數(shù)據(jù)結(jié)構(gòu)實現(xiàn),不同的存儲引擎采用不同的索引結(jié)構(gòu)來優(yōu)化查詢性能。
常用的數(shù)據(jù)結(jié)構(gòu)有:
- B樹(B-Tree)
- B+樹(B+Tree)(InnoDB實際采用)
- Hash
- R-Tree(空間索引)
MySQL主要就是使用B+樹。
在了解B樹和B+樹之前,我們先來了解一下二叉樹:
二叉樹(二叉搜索樹)
- 二叉搜索樹(Binary Search Tree, BST)是一種特殊的二叉樹:
- 左子樹所有節(jié)點值 < 根節(jié)點值
- 右子樹所有節(jié)點值 > 根節(jié)點值
- 左右子樹也分別是BST
優(yōu)點:
- 邏輯簡單:易于理解和實現(xiàn)
- 有序性:中序遍歷可得有序序列
- 二分查找:理想情況下查詢效率高
缺點:
- 不平衡風險:可能退化成鏈表(復(fù)雜度→O(n))
- 不適合磁盤存儲:節(jié)點隨機分布導(dǎo)致大量磁盤I/O
下面就是最壞情況下的二叉樹,直接演化為了一個鏈表形式。
B樹(B-Tree)
B-Tree,B樹是一種自平衡的樹數(shù)據(jù)結(jié)構(gòu),相對于二叉樹,B樹每個節(jié)點可以有多個分支,即多叉。它保持數(shù)據(jù)有序,并允許進行高效的搜索、順序訪問、插入和刪除操作。
以一顆最大度數(shù)(max-degree)為5(5階)的b-tree為例,那這個B樹每個節(jié)點最多存儲4個key
B樹的主要特性:
- 多路平衡搜索樹:每個節(jié)點可以有多個子節(jié)點。
- 自平衡:樹始終保持平衡狀態(tài)。
- 有序存儲:節(jié)點中的鍵(key)按順序排列。
- 適合外存:設(shè)計用于減少磁盤訪問次數(shù)。
B+樹(B+Tree)
B+Tree是在BTree基礎(chǔ)上的一種優(yōu)化,具有比B樹更適合外部存儲的特性,InnoDB存儲引擎就是用B+Tree實現(xiàn)其索引結(jié)構(gòu)。
B+樹的主要特點:
- 多路平衡:每個節(jié)點可以有多個子節(jié)點,保持樹的平衡
- 分層存儲:數(shù)據(jù)只存儲在葉子節(jié)點,內(nèi)部節(jié)點只存儲鍵值(索引)
- 順序訪問:所有葉子節(jié)點通過指針連接成一個有序鏈表
B+樹與B樹的比較
特性 | B樹 | B+樹 |
---|---|---|
數(shù)據(jù)存儲 | 所有節(jié)點都可存儲數(shù)據(jù) | 僅葉子節(jié)點存儲數(shù)據(jù) |
查找性能 | 可能提前終止(非葉子節(jié)點找到) | 必須到達葉子節(jié)點 |
范圍查詢 | 需要中序遍歷 | 通過葉子鏈表高效掃描 |
空間利用率 | 內(nèi)部節(jié)點存儲數(shù)據(jù)占用更多空間 | 內(nèi)部節(jié)點更緊湊 |
穩(wěn)定性 | 查詢路徑長度不一致 | 所有查詢路徑長度相同 |
實現(xiàn)復(fù)雜度 | 相對簡單 | 相對復(fù)雜(需維護葉子鏈表) |
總的來說,由于B+樹獨特的數(shù)據(jù)存儲方式:
- B+樹的磁盤讀寫代價更低。
- B+樹的查詢效率更加穩(wěn)定。
- B+樹更便于掃庫和區(qū)間查詢。
3.總結(jié)
3.1 什么是索引?
- 索引(index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)(有序)。
- 提高數(shù)據(jù)檢索的效率,降低數(shù)據(jù)庫的IO成本(不需要全表掃描)。
- 通過索引列對數(shù)據(jù)進行排序,降低數(shù)據(jù)排序的成本,降低了CPU的消耗。
3.2 索引的底層數(shù)據(jù)結(jié)構(gòu)?
MySQL的InnoDB引擎采用的B+樹的數(shù)據(jù)結(jié)構(gòu)來存儲索引
- 階數(shù)更多,路徑更短。
- 磁盤讀寫代價B+樹更低,非葉子節(jié)點只存儲指針,葉子階段存儲數(shù)據(jù)。
- B+樹便于掃庫和區(qū)間查詢,葉子節(jié)點是一個雙向鏈表。
3.3 為什么 B+Tree 是主流?
- 磁盤友好:減少 I/O 次數(shù)(矮胖的樹形結(jié)構(gòu))。
- 范圍查詢高效:葉子節(jié)點鏈表避免回溯。
- 緩存利用率高:非葉子節(jié)點僅存鍵值,可緩存更多索引。
到此這篇關(guān)于MySQL數(shù)據(jù)庫索引及底層數(shù)據(jù)結(jié)構(gòu)詳解的文章就介紹到這了,更多相關(guān)mysql索引底層數(shù)據(jù)結(jié)構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解 Mysql查詢結(jié)果順序按 in() 中ID 的順序排列
這篇文章主要介紹了詳解 Mysql查詢結(jié)果順序按 in() 中ID 的順序排列的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09解決MySQL數(shù)據(jù)庫中文模糊檢索問題的方法
解決MySQL數(shù)據(jù)庫中文模糊檢索問題的方法...2007-11-11