MySql索引常見問題,B+樹詳解

什麼是索引?

索引是一種能幫助 MySQL 提高查詢效率的數據結構。

索引分別有哪些優點和缺點?

索引的優點如下:

  • 快速訪問數據表中的特定信息,提高檢索速度。
  • 創建唯一性索引,保證數據表中每一行數據的唯一性。
  • 加速表與表之間的連接。
  • 使用分組和排序進行數據檢索時,可以顯著減少查詢中分組和排序的時間。

索引的缺點:

  • 雖然提高了的查詢速度,但卻降低了更新表的速度,比如 update、insert,因爲更新數據時,MySQL 不僅要更新數據,還要更新索引文件;
  • 建立索引會佔用磁盤文件的索引文件。

使用索引注意事項:

  • 使用短索引,短索引不僅可以提高查詢速度,更能節省磁盤空間和 I/O 操作;
  • 索引列排序,MySQL 查詢只使用一個索引,因此如果 where 子句中已經使用了索引的話,那麼 order by 中的列是不會使用索引的,因此數據庫默認排序可以符合要求的情況下,不要進行排序操作;儘量不要包含多個列的排序,如果需要最好給這些列創建複合索引;
  • like 語句操作,一般情況下不鼓勵使用 like 操作,如果非使用不可, 注意 like “%aaa%” 不會使用索引,而like "aaa%"可以使用索引;
  • 不要在列上進行運算;
  • 不適用 NOT IN 和 <> 操作。

索引有幾種類型?分別如何創建?

MySQL 的索引有兩種分類方式:邏輯分類和物理分類。 按照邏輯分類,索引可分爲:

  • 主鍵索引:一張表只能有一個主鍵索引,不允許重複、不允許爲 NULL;
  • 唯一索引:數據列不允許重複,允許爲 NULL 值,一張表可有多個唯一索引,但是一個唯一索引只能包含一列,比如身份證號碼、卡號等都可以作爲唯一索引;
  • 普通索引:一張表可以創建多個普通索引,一個普通索引可以包含多個字段,允許數據重複,允許 NULL 值插入;
  • 全文索引:讓搜索關鍵詞更高效的一種索引。

按照物理分類,索引可分爲:

  • 聚集索引:一般是表中的主鍵索引,如果表中沒有顯示指定主鍵,則會選擇表中的第一個不允許爲 NULL 的唯一索引,如果還是沒有的話,就採用 Innodb 存儲引擎爲每行數據內置的 6 字節 ROWID 作爲聚集索引。每張表只有一個聚集索引,因爲聚集索引的鍵值的邏輯順序決定了表中相應行的物理順序。聚集索引在精確查找和範圍查找方面有良好的性能表現(相比於普通索引和全表掃描),聚集索引就顯得彌足珍貴,聚集索引選擇還是要慎重的(一般不會讓沒有語義的自增 id 充當聚集索引);
  • 非聚集索引:該索引中索引的邏輯順序與磁盤上行的物理存儲順序不同(非主鍵的那一列),一個表中可以擁有多個非聚集索引。

各種索引的創建腳本如下:

-- 創建主鍵索引
alter table t add primary key add (`id`);
-- 創建唯一索引
alter table t add unique (`username`);
-- 創建普通索引
alter table t add index index_name (`username`);
-- 創建全文索引
alter table t add fulltext (`username`);

主索引和唯一索引有什麼區別?

  • 主索引不能重複且不能爲空,唯一索引不能重複,但可以爲空;

  • 一張表只能有一個主索引,但可以有多個唯一索引;

  • 主索引的查詢性能要高於唯一索引。

    因爲普通索引的查詢會多執行一次檢索操作。比如主鍵查詢 select * from t where id=10 只需要搜索 id 的這棵 B+ 樹,而普通索引查詢 select * from t where f=3 會先查詢 f 索引樹,得到 id 的值之後再去搜索 id 的 B+ 樹,因爲多執行了一次檢索,所以執行效率就比主鍵索引要低。

什麼叫回表查詢?

普通索引查詢到主鍵索引後,回到主鍵索引樹搜索的過程,我們稱爲回表查詢。

參考SQL:

mysql> create table T(
id int primary key, 
k int not null, 
name varchar(16),
index (k))engine=InnoDB;

如果語句是 select * from T where ID=500,即主鍵查詢方式,則只需要檢索主鍵 ID 字段。

mysql>  select * from T where ID=500;
+-----+---+-------+
| id  | k | name  |
+-----+---+-------+
| 500 | 5 | name5 |
+-----+---+-------+

如果語句是 select * from T where k=5,即普通索引查詢方式,則需要先搜索 k 索引樹,得到 ID 的值爲 500,再到 ID 索引樹搜索一次,這個過程稱爲回表查詢。

mysql> select * from T where k=5;
+-----+---+-------+
| id  | k | name  |
+-----+---+-------+
| 500 | 5 | name5 |
+-----+---+-------+

也就是說,基於非主鍵索引的查詢需要多掃描一棵索引樹。因此,我們在應用中應該儘量使用主鍵查詢。

索引的常見存儲算法有哪些?

  • 哈希存儲法:以 key、value 方式存儲,把值存入數組中使用哈希值確認數據的位置,如果發生哈希衝突,使用鏈表存儲數據;
  • 有序數組存儲法:按順序存儲,優點是可以使用二分法快速找到數據,缺點是更新效率,適合靜態數據存儲;
  • 搜索樹:以樹的方式進行存儲,查詢性能好,更新速度快。

InnoDB 爲什麼要使用 B+ 樹,而不是 B 樹、Hash、紅黑樹或二叉樹?

因爲 B 樹、Hash、紅黑樹或二叉樹存在以下問題:

  • B 樹:不管葉子節點還是非葉子節點,都會保存數據,這樣導致在非葉子節點中能保存的指針數量變少(有些資料也稱爲扇出),指針少的情況下要保存大量數據,只能增加樹的高度,導致IO操作變多,查詢性能變低;
  • Hash:雖然可以快速定位,但是沒有順序,IO 複雜度高;
  • 二叉樹:樹的高度不均勻,不能自平衡,查找效率跟數據有關(樹的高度),並且 IO 代價高;
  • 紅黑樹:樹的高度隨着數據量增加而增加,IO 代價高。

爲什麼 InnoDB 要使用 B+ 樹來存儲索引?

B+Tree 中的 B 是 Balance,是平衡的意思,它在經典 B Tree 的基礎上進行了優化,增加了順序訪問指針,在B+Tree 的每個葉子節點增加一個指向相鄰葉子節點的指針,就形成了帶有順序訪問指針的 B+Tree,這樣就提高了區間訪問性能:如果要查詢 key 爲從 18 到 49 的所有數據記錄,當找到 18 後,只需順着節點和指針順序遍歷就可以一次性訪問到所有數據節點,極大提到了區間查詢效率(無需返回上層父節點重複遍歷查找減少 IO 操作)。

索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲的磁盤上,這樣的話,索引查找過程中就要產生磁盤 IO 消耗,相對於內存存取,IO 存取的消耗要高几個數量級,所以索引的結構組織要儘量減少查找過程中磁盤 IO 的存取次數,從而提升索引效率。 綜合所述,InnDB 只有採取 B+ 樹的數據結構存儲索引,才能提供數據庫整體的操作性能。

B+樹的特徵:

1.有k個子樹的中間節點包含有k個元素(B樹中是k-1個元素),每個元素不保存數據,只用來索引,所有數據都保存在葉子節點。

2.所有的葉子結點中包含了全部元素的信息,及指向含這些元素記錄的指針,且葉子結點本身依關鍵字的大小自小而大順序鏈接。

3.所有的中間節點元素都同時存在於子節點,在子節點元素中是最大(或最小)元素。

B+樹的優勢:

1.單一節點存儲更多的元素,使得查詢的IO次數更少。

2.所有查詢都要查找到葉子節點,查詢性能穩定。

3.所有葉子節點形成有序鏈表,便於範圍查詢。

所有的中間節點元素都同時存在於子節點,在子節點元素中是最大(或最小)元素。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章