Mysql索引詳解

一、爲什麼需要索引?(索引的優缺點)

1、索引產生的意義

沒有索引行不行?答案是肯定的,可以不使用索引,在數據庫中將數據整齊的排列在磁盤陣列中,當獲取數據的時候只需要逐個搜索,並返回結果,但是 如果開發的應用有幾百上千萬甚至億級別的數據,那麼不深入瞭解索引的原理, 寫出來程序就根本跑不動,光查一個數據庫就得好幾天,因此就需要索引,能夠快速的查找的需要的數據。

2、索引的優缺點

  • 優點

1、極大地加速了索引過程,減少IO次數
2、創建唯一索引,保證了數據庫表中的唯一性
3、加速了表與表之間的連接
4、針對分組和排序檢索時,能夠顯著減少查詢查詢中的分組和排序時間

  • 缺點

1、索引表佔據物理空間
2、數據表中的數據增加、修改、刪除的同時需要去動態維護索引表,降低了數據的維護速度

二、索引的分類

1、唯一索引:表上一個字段或者多個字段的組合建立的索引,這些字段組合起來能夠確定唯一,允許存在空值(只允許存在一條空值)
2、非唯一索引:表上一個字段或者多個字段的組合建立的索引,可以重複,不需要唯一
3、主鍵索引:(主索引)根據主鍵pk_clolum(length)建立索引,不允許重複,不允許空值;
4、聚合索引:表中記錄的物理順序與鍵值的索引順序相同
5、非聚合索引:表中記錄的物理順序與鍵值的索引順序無關
6、全文索引:在某個字段設置全文索引後,根據特定語法查找滿足條件的字段;

1、全文搜索在 MySQL 中是一個 FULLTEXT 類型索引。FULLTEXT 索引在 MySQL 5.6 版本之後支持 InnoDB,而之前的版本只支持 MyISAM 表。
2、目前只有char、varchar,text 列上可以創建全文索引。
3、 like “value%” 可以使用索引,但是對於 like “%value%” 這樣的方式,執行全表查詢

7、普通索引:用表中的普通列構建的索引,沒有任何限制
8、組合索引:用多個列組合 構建的索引,但是在使用過程中有諸多規則,遵循最左前綴原則,順序至關重要
9、Hash索引(Memory存儲引擎)是通過索引列的值計算出hashCode,之後在相應的物理位置存取索引列的值,由於hashCode的唯一性,因此Hash索引不能進行範圍查找或者是順序查找。

三、B樹-數據庫索引原理

轉載自博客:https://blog.csdn.net/endlu/article/details/51720299

1、B樹(平衡多路查找樹)

特性:

  • 樹中每個結點最多含有m個孩子(m>=2);
  • 除根結點和葉子結點外,其它每個結點至少有[ceil(m / 2)]個孩子(其中ceil(x)是一個取上限的函數);
  • 若根結點不是葉子結點,則至少有2個孩子(特殊情況:沒有孩子的根結點,即根結點爲葉子結點,整棵樹只有一個根節點);
  • 所有葉子結點都出現在同一層,葉子結點不包含任何關鍵字信息(可以看做是外部接點或查詢失敗的接點,實際上這些結點不存在,指向這些結點的指針都爲null);
  • 每個非終端結點中包含有n個關鍵字信息: (P1,K1,P2,K2,P3,…,Kn,Pn+1)。其中:
    a) Ki (i=1…n)爲關鍵字,且關鍵字按順序升序排序K(i-1)< Ki。
    b) Pi爲指向子樹根的接點,且指針P(i)指向子樹種所有結點的關鍵字均小於Ki,但都大於K(i-1)。
    c) 關鍵字的個數n必須滿足: [ceil(m / 2)-1]<= n <= m-1。

在這裏插入圖片描述

2、B+樹

B+樹特有:
1.有n棵子樹的結點中含有n個關鍵字; (而B樹是n棵子樹有n-1個關鍵字)
2.所有的葉子結點中包含了全部關鍵字的信息,及指向含有這些關鍵字記錄的指針,且葉子結點本身依關鍵字的大小自小而大的順序鏈接。(而B樹的葉子節點並沒有包括全部需要查找的信息)
3.所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。 (而B 樹的非終節點也包含需要查找的有效信息)

在這裏插入圖片描述

3、B+樹的優勢

1、B+樹磁盤讀寫次數更低
因爲B+樹非葉子結點只是相當於一個索引,會將所有關鍵字具體信息都存儲葉子結點,也就導致B+樹能夠存儲更加多的關鍵字數量,一次性讀入內存的關鍵字數量增加,IO讀寫次數減少

在索引查找的時候,B+樹的搜索方式是首先找到一個搜索下界,也就是滿足條件的最低值,之後通過中序遍歷的方式查找,而B+樹在查找到搜索下界後,直接通過鏈指針開始查找關鍵字信息

2、B±tree的查詢效率更加穩定
由於非終結點不存儲數據,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。

四、聚合索引(InNoDB存儲引擎)與非聚合索引(MyISAM存儲引擎)

在這裏插入圖片描述

1、聚合索引

1、選擇B+樹作爲存儲結構
2、聚合索引必須有主鍵、沒有顯示指定主鍵,就Mysql會自動選擇可以標識數據記錄的列,如果沒有這樣的列,會生成隱含字段作爲主鍵,類型爲long int ;
3、在InnoDb上會選擇自增字段作爲主鍵,是爲了維持B+樹的分裂特性,順序添加到當前索引的後續位置,當達到最大就會分裂產生新的頁,也不需要移動原有的順序
4、聚合索引有主索引和輔助索引,主索引葉子結點存儲鍵值對應的數據本身輔助索引葉子結點存儲主鍵鍵值
5、由於輔助索引存儲的是主鍵鍵值,因此按照輔助索引搜索的時候需要檢索兩遍,第一遍找到對應的主鍵,第二遍在主索引到達葉子結點中找到數據

2、非聚合索引

1、選擇B+樹作爲存儲結構
2、非聚合索引有主索引和輔助索引(兩個索引幾乎一樣),但是主索引不允許爲空,現在就需要考慮在索引分類中介紹的非聚合索引的概念,由於物理順序與索引順序不同,因此每一個葉子節點存儲的是指向鍵值對應的數據的物理地址(數據記錄的地址)
3、非聚簇索引的數據表和索引表是分開存儲的
4、獲取數據的方式是首先根據B+樹獲取索引,取出對應數據記錄的地址,之後再去讀取相應的數據記錄
5、只有在MyISAM中才能使用FULLTEXT索引。(mysql5.6以後innoDB也支持全文索引)
6、輔助索引的意義:如果給出的查詢條件不是主鍵,此時就使用輔助索引,並且使用輔助索引不需要使用主索引

1、使用聚合索引的場景:

  • 某列包含小數目的不同值

  • 排序和範圍索引(主鍵遞增)
    2、使用非聚合索引的場景:

  • 某列包含大數目的不同值

  • 頻繁更新的列,因爲非聚集索引添加記錄時,不會引起數據順序的重組

3、InNoDB與MyISAM異同

博客(自己還未閱讀):https://www.cnblogs.com/y-rong/p/8110596.html

1、InnoDB 支持事務,支持行級別鎖定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
2、MyISAM 不支持事務,支持表級別鎖定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
3、Memory 不支持事務,支持表級別鎖定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;
4、MyISAM引擎不支持外鍵,InnoDB支持外鍵
5、MyISAM引擎的表在大量高併發的讀寫下會經常出現表損壞的情況
6、對於count()查詢來說MyISAM更有優勢,MyISAM直接通過計數器獲取。InnoDB需要通過掃描全部數據
7、MyISAM引擎的表的查詢、更新、插入的效率要比InnoDB高,如果你的數據量是百萬級別的,並且沒有任何的事務處理,那麼用MyISAM是性能最好的選擇。,並且MyISAM可以節省很多內存

五、組合索引(覆蓋索引)

基於多個字段創建的索引就是組合索引。

組合索引規則:
1、最左原則:索引是key index (a,b,c). 可以支持a | a,b| a,b,c 3種組合進行查找,但不支持 b,c進行查找 .當最左側字段是常量引用時,索引就十分有效。(電話簿中利用姓名查找人,姓和名分別是不同的列,知道姓電話簿有用,知道姓知道名電話簿有用,知道名不知道姓電話簿無用)

補充:
key_len:EXPLAIN執行計劃中有一列 key_len用於表示本次查詢中,所選擇的索引長度有多少字節,通常我們可藉此判斷聯合索引有多少列被選擇了。

1、index Key:索引數據範圍

  • 下邊界
    MySQL利用=、>=、> 來確定下邊界(first key),利用最左原則,首先判斷第一個索引鍵值在where條件中是否存在,如果存在,則判斷比較符號,如果爲(=,>=)中的一種,加入下邊界的界定,然後繼續判斷下一個索引鍵,如果存在且是(>),則將該鍵值加入到下邊界的界定,停止匹配下一個索引鍵;如果不存在,直接停止下邊界匹配。
  • 上邊界
    上邊界(last key)和下邊界(first key)類似,首先判斷是否是否是(=,<=)中的一種,如果是,加入界定,繼續下一個索引鍵值匹配,如果是(<),加入界定,停止匹配

2、Index Filter :用於過濾索引查詢範圍中不滿足查詢條件的記錄

Index Filter的提取規則:同樣從索引列的第一列開始,檢查其在where條件中是否存在:若存在並且where條件僅爲 =,則跳過第一列繼續檢查索引下一列,下一索引列採取與索引第一列同樣的提取規則;若where條件爲 >=、>、<、<= 其中的幾種,則跳過索引第一列,將其餘where條件中索引相關列全部加入到Index Filter之中;若索引第一列的where條件包含 =、>=、>、<、<= 之外的條件,則將此條件以及其餘where條件中索引相關列全部加入到Index Filter之中;若第一列不包含查詢條件,則將所有索引相關條件均加入到Index Filter之中。

以上index Key和Index Filter都是通過索引列來實現的,而Table Filter是針對非索引列

3、Table Filter :無法使用索引過濾,使用表過濾

提取規則:所有不屬於索引列的查詢條件,均歸爲Table Filter之中。

where索引過程:

圖片轉載自:http://www.fordba.com/spend-10-min-to-understand-how-mysql-use-index.html

在這裏插入圖片描述

六、索引失效

1、在where後使用or,導致索引失效(儘量少用or)
2、使用like ,like查詢是以%開頭,以%結尾不會失效
3、不符合最左原則
4、如果列類型是字符串,那一定要在條件中將數據使用引號引用起來,否則不使用索引
5、 使用in導致索引失效
6、使用mysql內部函數導致索引失效,可能會導致索引失效。
7、如果MySQL估計使用索引比全表掃描更慢,則不使用索引

七、索引Demo

CREATE TABLE table_name[col_name data type] [unique|fulltext][index|key][index_name](col_name[length])[asc|desc]

  • unique|fulltext爲可選參數,分別表示唯一索引、全文索引
  • index和key爲同義詞,兩者作用相同,用來指定創建索引
  • col_name爲需要創建索引的字段列,該列必須從數據表中該定義的多個列中選擇
  • index_name指定索引的名稱,爲可選參數,如果不指定,默認col_name爲索引值
  • length爲可選參數,表示索引的長度,只有字符串類型的字段才能指定索引長度
  • asc或desc指定升序或降序的索引值存儲
  • 創建數據庫並添加數據
CREATE TABLE `students` (
  `stud_id` int(11) NOT NULL,
  `name` varchar(50) NOT NULL,
  `email` varchar(50) NOT NULL,
  `phone` varchar(30) NOT NULL,
  `create_date` date DEFAULT NULL,
  `content` text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `students` (`stud_id`, `name`, `email`, `phone`, `create_date`, `content`) VALUES
(1, 'admin', '[email protected]', '18729902095', '1983-06-25', 'i am robin'),
(2, 'root', '[email protected]', '2', '1983-12-25', 'i am xiaoluo'),
(3, '110', '[email protected]', '3dsad', '2017-04-28', 'i am lili');

1、創建普通索引

  • 查看索引show INDEX from students
  • 創建索引方式

1.直接創建:CREATE INDEX index_name ON student(name);
2、修改表結構方式創建索引:alter TABLE students ADD INDEX index_name2(name);
3、創建表的時候建立索引:添加:index index_name3(name)
創建後的索引:
在這裏插入圖片描述
查看是否通過索引能夠獲取數據:EXPLAIN SELECT name FROMstudentsWHERE name='admin'
通過索引獲取數據:
在這裏插入圖片描述

-刪除索引: DROP INDEX index_name ON table_name;
                    alter table表名drop index 索引名;

2、創建唯一索引(Index前邊添加unique)

1、創建郵箱索引:

CREATE UNIQUE INDEX index_email on students(email);
ALTER TABLE students ADD UNIQUE INDEX index_mail2(email);
創建表的時候添加:UNIQUE index_name_unique(email)

3、創建主鍵索引

主鍵索引是一種特殊的唯一索引,一個表只能有一個主鍵,不允許有空值。一般是在建表的時候同時創建主鍵索引:
1、創建郵箱索引:

ALTER TABLE students ADD PRIMARY KEY(stud_id);
創建表的時候添加:primary key(‘stud_id’)

4、創建全文索引

1、創建全文索引
創建表的時候添加:fulltext(content)
CREATE FULLTEXT INDEX index_content on students(content);
ALTER table students ADD FULLTEXT INDEX index_content2(content);
2、show index from students;
在這裏插入圖片描述
3、全文索引查詢:

SELECT * FROM `students` WHERE MATCH(`content`) against('robin')

在這裏插入圖片描述
4、建立一個聯合索引
添加另外一個全文索引:ALTER TABLE students ADD FULLTEXT INDEX email_content(email,content);
聯合全文索引:SELECT * FROMstudentsWHERE MATCH(email,content) against('student robin')
在這裏插入圖片描述

八、引用博客

【1】實戰demo:https://blog.csdn.net/u010648555/article/details/81102957
【2】B樹與B+樹:https://blog.csdn.net/endlu/article/details/51720299
【3】聚合索引與非聚合索引概念:https://blog.csdn.net/tongdanping/article/details/79878302
【4】InNoDB與MyISAM差別:https://www.cnblogs.com/y-rong/p/8110596.html
【5】組合索引:http://www.fordba.com/spend-10-min-to-understand-how-mysql-use-index.html
【6】Mysql如何利用索引,通過組合索引:http://hedengcheng.com/?p=577
圖片:http://www.fordba.com/spend-10-min-to-understand-how-mysql-use-index.html
【7】索引使用規則;https://www.cnblogs.com/duanxz/p/5244703.html

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