数据库索引类型介绍及其优缺点、区别、适用场景
索引
索引分為主鍵索引、唯一索引、普通索引、聚集索引、全文索引幾種,而索引其實(shí)就是在無序的數(shù)據(jù)中建立索引,每次查詢可以根據(jù)索引迅速查到我們想要的數(shù)據(jù)(就像字典的目錄a-z一樣)
-
優(yōu)點(diǎn)
- 提高數(shù)據(jù)查找速度
- 提高group by、order by分組與排序的時間
-
缺點(diǎn)
- 每增加數(shù)據(jù)都需要更新索引,隨者數(shù)據(jù)量增大,索引維護(hù)成本會增加
- 占用一定的存儲空間,.myi后綴的文件存儲的就是索引文件。
索引類型
主鍵索引
數(shù)據(jù)列不允許重復(fù),不允許為NULL,可以被引用為外鍵,一個表只能有一個主鍵索引
唯一索引
數(shù)據(jù)列不允許重復(fù),允許為NULL值,不可以被引用為外鍵,一個表允許多個列創(chuàng)建唯一索引
普通索引
基本的索引類型,沒有唯一性限制,允許為NULL值,不可以被引用為外鍵,一個表可以有多個普通索引
主鍵索引、唯一索引、普通索引區(qū)別:
| 主鍵索引 | 否 | 否 | 是 | 僅有一個 |
| 唯一索引 | 否 | 是 | 否 | 允許多個 |
| 普通索引 | 是 | 是 | 否 | 允許多個 |
表中可以看出約束是從高到低,對比表種內(nèi)容然后依據(jù)不同場景進(jìn)行使用
聚集索引(聚簇索引)
在聚集索引中,表中數(shù)據(jù)行的物理位置與邏輯值(索引和數(shù)據(jù)為同一個文件)的順序相同,一個表中只能包含一個聚集索引,因為物理順序只能有一個。聚集索引通常提供更快的數(shù)據(jù)訪問速度。
其中 InnoDB采用的就是聚簇索引,數(shù)據(jù)和索引文件為一個idb文件,表數(shù)據(jù)文件本身就是主索引,相鄰的索引臨近存儲。 葉節(jié)點(diǎn)data域保存了完整的數(shù)據(jù)記錄(數(shù)據(jù)[除主鍵id外其他列data]+主索引[索引key:表主鍵id])。 葉子節(jié)點(diǎn)直接存儲數(shù)據(jù)記錄,以主鍵id為key,葉子節(jié)點(diǎn)中直接存儲數(shù)據(jù)記錄。(底層存儲結(jié)構(gòu): frm -表定義、 ibd: innoDB數(shù)據(jù)&索引文件)
(1)如果表定義了主鍵,則PK就是聚集索引;
(2)如果表沒有定義主鍵,則第一個非空唯一索引(not NULL unique)列是聚集索引;
(3)否則,InnoDB會創(chuàng)建一個隱藏的row-id作為聚集索引;
非聚簇索引
索引和數(shù)據(jù)分開的索引。
其中MyISAM底層采用的就是非聚簇索引,使用myi索引文件和myd數(shù)據(jù)文件分離,索引文件僅保存數(shù)據(jù)記錄的指針地址。葉子節(jié)點(diǎn)data域存儲指向數(shù)據(jù)記錄的指針地址。(底層存儲結(jié)構(gòu): frm -表定義、 myi -myisam索引、 myd-myisam數(shù)據(jù))
覆蓋索引
所謂覆蓋索引就是指索引中包含了查詢中的所有字段,這種情況下就不需要再進(jìn)行回表查詢了
MySQL 中只能使用 B-Tree 索引做覆蓋索引,因為哈希索引等都不存儲索引的列的值,覆蓋索引對于 MyISAM 和 InnoDB 都非常有效,可以減少系統(tǒng)調(diào)用和數(shù)據(jù)拷貝等時間
組合索引
使用多個列來組成一個索引,比如B-Tree的方式
全文索引
主要用于海量數(shù)據(jù)的搜索,比如淘寶、京東對商品的搜索就可以建立全文索引(不可能用like模糊匹配吧),這個類型在mysql5.6開始支持InnoDB引擎的全文索引,功能沒有專業(yè)搜索引擎比如solr、es豐富,如果需求簡單,可以使用全文索引
適用場景:適用于海量數(shù)據(jù)的關(guān)鍵字模糊搜索,比如簡易版的搜索引擎
索引的實(shí)現(xiàn)方式
B-Tree索引
InnoDB使用的是B-Tree算法,即每個葉子節(jié)點(diǎn)包含指向下一個葉子節(jié)點(diǎn)的指針,就像一個樹一樣
適用場景:最常用的一個索引類型,可以適用于多種場景
工作原理:B-Tree索引中,聯(lián)合索引中的索引項會先根據(jù)第一個索引列進(jìn)行排序,第一個索引列相同的情況下,會再按照第二個索引列進(jìn)行排序,依次類推。
可以應(yīng)用到B-Tree索引的情況:
無法使用到B-Tree索引的情況:
哈希索引
如果在列上建立索引,則針對每一行數(shù)據(jù),存儲引擎會根據(jù)所有的索引列計算出一個哈希碼,每一個行計算出的哈希碼會組成一個哈希表,同時在哈希表中存儲了指向每個數(shù)據(jù)行的指針。
哈希表結(jié)構(gòu)如下:
適用場景:僅作等值匹配且數(shù)據(jù)重復(fù)率低且對索引查找速度要求高的情況
可以應(yīng)用到哈希索引的情況:
無法使用到哈希索引的情況:
其中,還有一個叫做“自適應(yīng)哈希索引”,是當(dāng)InnoDB注意到某些索引的使用頻率很高時,會在B-Tree索引之上再建立一層哈希索引,以提高查詢效率
空間數(shù)據(jù)索引(R-Tree)
空間索引可用于地理數(shù)據(jù)存儲,它需要GIS相關(guān)函數(shù)的支持,由于MySQL的GIS支持并不完
善,所以該索引方式在MySQL中很少有人使用。
擴(kuò)展
什么是回表
如果 select 所需獲得列中有大量的非索引列,索引就需要到表中找到相應(yīng)的列的信息,這就叫回表
比如如下例子,先使用普通索引查詢除出ID,然后再去聚簇索引查詢具體數(shù)據(jù)的過程就叫左做回表
如何避免回表?
使用聚集索引(主鍵或第一個唯一索引)就不會回表,普通索引就會回表
比如select id, name, sex from user;,將單列索引(name)升級為聯(lián)合索引(name, sex),即可避免回表,因為要查詢的name和sex都在索引中了
索引下推
MySQL 5.6引入了索引下推優(yōu)化,可以在索引遍歷過程中,對索引中包含的字段先做判斷,過濾掉不符合條件的記錄,減少回表字?jǐn)?shù)
select * from tuser where name like '張 %' and age=10 and ismale=1;沒有索引下推:首先根據(jù)索引來查找記錄,然后再根據(jù)where條件來過濾記錄(回表)
有索引下推:MySQL會在取出索引的同時,判斷是否可以進(jìn)行where條件過濾再進(jìn)行索引查詢(回表)
唯一索引導(dǎo)致死鎖
如圖所示,有三個事務(wù)同時插入同一個記錄,導(dǎo)致唯一索引沖突的過程:
死鎖發(fā)生過程:
根本原因:
唯一索引導(dǎo)致,本質(zhì)是并發(fā)請求導(dǎo)致一個數(shù)據(jù)重復(fù)插入或是網(wǎng)絡(luò)抖動造成
解決方案:
總結(jié)
以上是生活随笔為你收集整理的数据库索引类型介绍及其优缺点、区别、适用场景的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ 什么是句柄?为什么会有句柄?HA
- 下一篇: SQLServer 2008 r2 安装