1,BTREE是多叉樹,多路徑搜索樹。有N棵子樹的節點它包含N-1個關鍵字,例如,有3個子樹的非葉子節點,那麼就有2個關鍵字,每一個關鍵字不保存數據,只用來存儲索引(在索引存儲數據時,將索引指向關鍵字的值也存儲進來。最終實現key = &get; value結構)。全部的數據最終都要落在葉子節點,全部的葉子節點包括關鍵字信息以及指向這些關鍵字的指針,並且葉子節點是根據關鍵字大小、順序連接的。全部的葉子節點都必須有個鏈表指針把數據串起來。因此,全部非葉子節點能夠當作索引部分,包括子樹中最大值或最小值關鍵字等信息。在btree索引下,獲取數據時只須要從索引樹的最小節點,一直不斷的向右進行遍歷就能夠快速的獲得想要的數據(這種遍歷有指針把數據串起來),不須要回溯到根節點, 這樣就能夠理解爲何innodb的主鍵索引不能用離散的數據。html
下圖爲2層btree結構:mysql
btree數據量分佈狀況:算法
2,哈希索引創建在哈希表的基礎上,它對每一個值採用精確查找。每一行都須要先計算哈希碼,比較好的哈希算法算出比較低的重複的度,這樣效率相對高一些。若是算出來的值是同樣的,那麼它須要再進行判斷哪一個值纔是想要的值,因此說在表裏面採用哈希索引,可是重複度又比較高,那麼哈希索引效率就比較低,可使用select crc32('xxx');計算出哈希碼,利用這個哈希值指向具體的數據位置。 sql
HASH索引PK BTREE索引:大量不一樣數據等值精確查詢,HASH索引效率一般比BTREE高;HASH索引不支持聯合索引的最左匹配規則(where a =? and b=? ,index(a,b,c)這樣沒法同時使用a,b,c,至關因而範圍查詢);HASH索引不支持排序;HASH索引不支持模糊查找;數據結構
下圖爲哈希索引:mvc
3,彙集索引,其實就是索引的組織方式,整個表存儲的邏輯順序根彙集索引的順序是一致的,也就是說彙集索引決定了整個表的物理的存儲的邏輯順序。mysql一個表只支持一個彙集索引。在innodb裏面彙集索引就是整個表,表就是彙集索引,由於innodb的彙集索引後面是整行數據(若是主鍵由多列組成,btree優先按第一列順序存儲),在彙集索引btree裏面每一個葉子節點最終存儲每行數據,這就是爲何在innodb裏面沒有任何條件count (*),它會優先選擇普通索引來完成掃描,而不是採用主鍵索引,由於若是掃彙集索引,掃描的數據量更大,產生的IO更大,若是掃描普通輔助索引,那麼它的數據結構一般來說比主鍵索引小。另外,爲了實現mvcc彙集索引還存儲了rollback point和事物ID。spa
innodb的普通索引葉子節點裏面存儲着主鍵索引的鍵值。彙集索引決定了物理表的存儲順序,若是彙集索引頻繁修改,可能會致使修改存儲的順序,那麼這個行數據會產生位移,產生數據離散IO。若是新增的數據太過離散,也會致使彙集索引存儲的位置相應的離散,也會致使隨機IO.指針
innodb的index extentions特性:mysql5.6.9版本之後,在innodb普通索引裏面存儲着主鍵鍵值,目的是根據普通索引掃描時能根據普通索引鍵值找到主鍵並找到對應的數據。以下圖:#官方文檔,https://dev.mysql.com/doc/refman/5.6/en/index-extensions.html日誌
create table innodb_table_monitorcode
(id int)engine=innodb;#隨便字段只要是innodb表,會把如下信息打印到日誌,建立後10s左右生效。
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESpaces WHERE NAME like '%t1%'; #5.7查看視圖才能夠
mysql> show create table zhangshuo\G *************************** 1. row *************************** Table: zhangshuo Create Table: CREATE TABLE `zhangshuo` ( `id` int(11) NOT NULL DEFAULT '0', `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
彙集索引的選擇:
a,含有大量非重複值的列;
b,被連續(順序)訪問的列;
c,返回大量結果集的查詢;
案例:
若是一個表很大,有1/3數據要刪除,若是是隨機刪除,會產不少空洞,刪完後產生的空洞不寫入,沒什麼影響,但這種刪除比較慢,由於須要對btree進行隨機掃描。刪完後索引樹會進行自旋,若是它的page填充因子比較低,例如把2頁合併成1頁,在合併中進行寫入會比較慢。 刪完後能夠執行alter table engine=innodb來整理碎片,可是會鎖表(重建整張表)或者從新定義主鍵列。建議使用pt-osc來完成表空間回收。
innodb主鍵索引分佈:
第一列:主鍵鍵值
第二列:事物ID
第三列:回滾指針
第四行:除了主鍵列之外其餘列的值
innodb普通非惟一索引分佈:
第一列是索引鍵值,由於是普通索引因此存在重複。
第二列是主鍵的列值。
innodb普通索引的key是自己列值,value對應的是主鍵的鍵值。這樣作的目的是咱們經過普通索引來掃描數據的時候咱們能夠快速的經過普通索引存儲的主鍵的鍵值找到對應的記錄。
innodb 主鍵索引特色:(這個表能夠理解成6行3個列)
普通索引的value指向的是主鍵的列:
innodb彙集索引特色驗證: