MySQL(六)------索引結構的理解

一、mysql索引從數據結構角度

1、B+樹索引

O(log(n))

B+樹是從平衡二叉樹演化來的,但是並不代表B+樹就是一個二叉樹。

BTREE索引就是一種將索引值按一定的算法,存入一個樹形的數據結構中(二叉樹),每次查詢都是從樹的入口root開始,依次遍歷node,獲取leaf。這是MySQL裏默認和最常用的索引類型。

爲什麼採用平衡查找樹

B+樹是一種平衡查找樹,爲什麼不直接使用二叉樹,很好理解,提高查找效率,防止二叉樹因數據的插入導致節點層級過高。參考jdk8中對HashMap底層數據結構的改進,當鏈表上個數超過8的時候,轉換爲紅黑樹(平衡查找樹)。

在這裏插入圖片描述
(效率較低的二叉查找樹)

既然二叉查找樹效率過低,那麼爲什麼不採用平衡二叉樹呢?

平衡二叉樹,任何節點間子樹的高度差不超過1,查找性能比較高。但是維護一棵平衡二叉樹的代價非常大。

在這裏插入圖片描述
(平衡二叉樹)

當插入新的鍵值(9),需要做如下變動

在這裏插入圖片描述
PS:引入網上圖片

維持一棵平衡二叉樹的開銷相對比較大的

B+樹特徵

在這裏插入圖片描述

  • B+樹的磁盤讀取代價低:分支節點沒有存儲數據,磁盤讀取,可以容納更多的內部節點;
  • B+樹的查詢效率更加穩定:分支節點都是葉子節點的索引,任意關鍵字的查找都必須從根節點走到分支節點,所有關鍵字查詢路徑長度相同,每個數據查詢效率相當;
  • B+樹便於執行掃庫操作:B+樹的數據都存儲在葉子節點上,分支節點均爲索引,只需掃一遍葉子即可;
  • 方便範圍查詢:所有葉子節點形成有序鏈表,方便範圍查詢。

2、hash索引

innodb本身的索引結構是B+tree索引,innodb會自動監控索引表,對應頻繁訪問的索引(熱點數據),在B+樹索引基礎上建立hash索引,來提高查找效率,但是對於客戶端是不可控的,隱式的。

hash索引特點

不支持範圍查詢:只支持包括 “=” "in "在內的等值查詢,不支持範圍;

不支持前綴匹配查詢:對於%的模糊查詢,hash索引不支持前綴匹配查詢

不能避免讀取行:哈希索引只包含哈希值和行指針,而不存儲字段值,所以不能使用索引中的值來避免讀取行。不過,訪問內存中的行的速度很快,所以大部分情況下這一點對性能的影響並不明顯。

無法用於排序:Hash索引是通過hash函數將,鍵值直接映射爲物理存儲地址,使時間複雜度降低到O(1).本身存儲是無序的,所以不能通過hash索引避免排序

無法使用部分索引列匹配查找:對於聯合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合併後再一起計算 Hash 值,而不是單獨計算 Hash 值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也無法被利用。

存在Hash衝突:hash索引本質採用hash表實現,當存在大量hash衝突,會採用鏈表結構。比如對性別、學歷等進行索引,因字段值重複性高,hash索引定位時,會造成命中查詢效率低下。

3、FULLTEXT索引

full-text主要是用來代替like "%***%"效率低下的問題

全文索引使用條件

表的存儲引擎是MyISAM,默認存儲引擎InnoDB不支持全文索引(新版本MYSQL5.6的InnoDB支持全文索引)

字段類型:只有字段類型爲char、varchar和text的字段才能設置全文索引。

MySQL自帶的全文索引只能對英文進行全文檢索,目前無法對中文進行全文檢索。

如果需要對包含中文在內的文本數據進行全文檢索,我們需要採用Sphinx(斯芬克斯)/Coreseek技術來處理中文

MySQL全文索引所能找到的詞的默認最小長度爲4個字符,使用MySQL自帶的全文索引時,如果查詢字符串的長度過短將無法得到期望的搜索結果

如何使用全文索引

alter table table_name add fulltext index(filed_1,filed_2);

SELECT * FROM table_name WHERE MATCH (filed_1,filed_2) AGAINST ('keyword');

4、R-Tree索引

r-tree在mysql很少使用,僅支持geometry數據類型,支持該類型的存儲引擎只有myisam、bdb、innodb、ndb、archive幾種。

二、按照索引種類來分

1、主鍵索引

設定爲主鍵後數據庫會自動建立索引

2、唯一索引

索引列的值必須唯一,但允許有空值

3、單列索引

即一個索引只包含單個列,一個表可以有多個單列索引

4、多列索引(複合索引)

即一個索引包含多個列

5、全文索引

對文本的內容進行分詞,進行搜索

三、創建索引的原則

1、更新頻繁的列不應設置索引

2、數據量小的表不要使用索引

3、區分度不大,重複數據多的字段不應設爲索引(如性別)

4、where 和 order by 涉及的列應考慮建立索引

5、業務上具有唯一特性的字段,即使是多個字段的組合,也建議建成唯一索引

四、mysql使用索引注意事項

1、使用!=以及<>不等於的時候,mysql不使用索引

2、當在字段時候函數的時候,mysql無法使用索引

3、在組合索引裏使用非第一個索引時也不使用索引

4、在使用like的時候,以%開頭,即"%***"的時候無法使用索引;在使用or的時候,要求or前後字段都有索引

5、避免對字段進行null的判斷,因爲索引不會生效(默認設置空字符串)

6、使用exist代替in(表中數據越多,exist的效率就比in要越大)

7、數據類型隱形轉換,索引不會生效,如select * from user where age='20',age表字段類型爲int,正確select * from user where age=20;

8、聯合索引必須要按照順序纔會生效。如聯合索引index(name,age),

9、不要使用 select *

10、多表關聯,關聯字段一定要有索引

11、執行計算不會命中索引,如:select * from test where a + 1 < 5

12、聯合索引如果查詢條件不包括索引最左邊的字段,不能命中索引。如index(a,b) ; select * from user where b = 'xxxx' 不生效

13、範圍條件查詢可以命中索引,但是查詢條件中用到兩個範圍列,則只有第一個會用到索引。select * from test where a > 5 and b < 10

14、範圍查詢和等值查詢同時存在,優先匹配等值查詢的索引select * from test where a = 1 and b < 10

五、如何創建索引

1、創建索引

#-創建普通索引
CREATE INDEX index_name ON table_name(col_name)
#創建唯一索引
CREATE UNIQUE INDEX index_name ON table_name(col_name)
#創建普通組合索引
CREATE INDEX index_name ON table_name(col_name_1,col_name_2);
#創建唯一組合索引
CREATE UNIQUE INDEX index_name ON table_name(col_name_1,col_name_2);

2、通過修改表結構創建索引

ALTER TABLE table_name ADD INDEX index_name(col_name);

3、創建表時直接指定索引

CREATE TABLE table_name (
    ID INT NOT NULL,col_name VARCHAR (16) NOT NULL,INDEX index_name (col_name)
);

4、刪除索引

#直接刪除索引
DROP INDEX index_name ON table_name;

#修改表結構刪除索引
ALTER TABLE table_name DROP INDEX index_name;

如果你覺得本篇文章對你有所幫助的話,麻煩請點擊頭像右邊的關注按鈕,謝謝!

技術在交流中進步,知識在分享中傳播

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