MySQL索引简介
索引是 MySQL 數(shù)據(jù)庫(kù)中的重要對(duì)象之一,用于快速找出某個(gè)列中有某一特定值的行。
?
為什么要使用索引
索引是 MySQL 中一種十分重要的數(shù)據(jù)庫(kù)對(duì)象。它是數(shù)據(jù)庫(kù)性能調(diào)優(yōu)技術(shù)的基礎(chǔ),常用于實(shí)現(xiàn)數(shù)據(jù)的快速檢索。
索引就是根據(jù)表中的一列或若干列按照一定順序建立的列值與記錄行之間的對(duì)應(yīng)關(guān)系表,實(shí)質(zhì)上是一張描述索引列的列值與原表中記錄行之間一一對(duì)應(yīng)關(guān)系的有序表。
在 MySQL 中,通常有以下兩種方式訪問(wèn)數(shù)據(jù)庫(kù)表的行數(shù)據(jù):
1) 順序訪問(wèn)
順序訪問(wèn)是在表中實(shí)行全表掃描,從頭到尾逐行遍歷,直到在無(wú)序的行數(shù)據(jù)中找到符合條件的目標(biāo)數(shù)據(jù)。這種方式實(shí)現(xiàn)比較簡(jiǎn)單,但是當(dāng)表中有大量數(shù)據(jù)的時(shí)候,效率非常低下。例如,在幾千萬(wàn)條數(shù)據(jù)中查找少量的數(shù)據(jù)時(shí),使用順序訪問(wèn)方式將會(huì)遍歷所有的數(shù)據(jù),花費(fèi)大量的時(shí)間,顯然會(huì)影響數(shù)據(jù)庫(kù)的處理性能。
2) 索引訪問(wèn)
索引訪問(wèn)是通過(guò)遍歷索引來(lái)直接訪問(wèn)表中記錄行的方式。使用這種方式的前提是對(duì)表建立一個(gè)索引,在列上創(chuàng)建了索引之后,查找數(shù)據(jù)時(shí)可以直接根據(jù)該列上的索引找到對(duì)應(yīng)記錄行的位置,從而快捷地查找到數(shù)據(jù)。索引存儲(chǔ)了指定列數(shù)據(jù)值的指針,根據(jù)指定的排序順序?qū)@些指針排序。
例如,在學(xué)生基本信息表 students 中,如果基于 student_id 建立了索引,系統(tǒng)就建立了一張索引列到實(shí)際記錄的映射表,當(dāng)用戶(hù)需要查找 student_id 為 12022 的數(shù)據(jù)的時(shí)候,系統(tǒng)先在 student_id 索引上找到該記錄,然后通過(guò)映射表直接找到數(shù)據(jù)行,并且返回該行數(shù)據(jù)。因?yàn)閽呙杷饕乃俣纫话氵h(yuǎn)遠(yuǎn)大于掃描實(shí)際數(shù)據(jù)行的速度,所以采用索引的方式可以大大提高數(shù)據(jù)庫(kù)的工作效率。
索引的分類(lèi)
索引的類(lèi)型和存儲(chǔ)引擎有關(guān),每種存儲(chǔ)引擎所支持的索引類(lèi)型不一定完全相同。根據(jù)存儲(chǔ)方式的不同,MySQL 中常用的索引在物理上分為以下兩類(lèi)。
1) B-樹(shù)索引
B-樹(shù)索引又稱(chēng)為 BTREE 索引,目前大部分的索引都是采用 B-樹(shù)索引來(lái)存儲(chǔ)的。B-樹(shù)索引是一個(gè)典型的數(shù)據(jù)結(jié)構(gòu),其包含的組件主要有以下幾個(gè):
- 葉子節(jié)點(diǎn):包含的條目直接指向表里的數(shù)據(jù)行。葉子節(jié)點(diǎn)之間彼此相連,一個(gè)葉子節(jié)點(diǎn)有一個(gè)指向下一個(gè)葉子節(jié)點(diǎn)的指針。
- 分支節(jié)點(diǎn):包含的條目指向索引里其他的分支節(jié)點(diǎn)或者葉子節(jié)點(diǎn)。
- 根節(jié)點(diǎn):一個(gè) B-樹(shù)索引只有一個(gè)根節(jié)點(diǎn),實(shí)際上就是位于樹(shù)的最頂端的分支節(jié)點(diǎn)。
基于這種樹(shù)形數(shù)據(jù)結(jié)構(gòu),表中的每一行都會(huì)在索引上有一個(gè)對(duì)應(yīng)值。因此,在表中進(jìn)行數(shù)據(jù)查詢(xún)時(shí),可以根據(jù)索引值一步一步定位到數(shù)據(jù)所在的行。
B-樹(shù)索引可以進(jìn)行全鍵值、鍵值范圍和鍵值前綴查詢(xún),也可以對(duì)查詢(xún)結(jié)果進(jìn)行 ORDER BY 排序。但 B-樹(shù)索引必須遵循左邊前綴原則,要考慮以下幾點(diǎn)約束:
- 查詢(xún)必須從索引的最左邊的列開(kāi)始。
- 查詢(xún)不能跳過(guò)某一索引列,必須按照從左到右的順序進(jìn)行匹配。
- 存儲(chǔ)引擎不能使用索引中范圍條件右邊的列。
2) 哈希索引
哈希(Hash)一般翻譯為“散列”,也有直接音譯成“哈希”的,就是把任意長(zhǎng)度的輸入(又叫作預(yù)映射,pre-image)通過(guò)散列算法變換成固定長(zhǎng)度的輸出,該輸出就是散列值。
哈希索引也稱(chēng)為散列索引或 HASH 索引。MySQL 目前僅有 MEMORY 存儲(chǔ)引擎和 HEAP 存儲(chǔ)引擎支持這類(lèi)索引。其中,MEMORY 存儲(chǔ)引擎可以支持 B- 樹(shù)索引和 HASH 索引,且將 HASH 當(dāng)成默認(rèn)索引。
HASH 索引不是基于樹(shù)形的數(shù)據(jù)結(jié)構(gòu)查找數(shù)據(jù),而是根據(jù)索引列對(duì)應(yīng)的哈希值的方法獲取表的記錄行。哈希索引的最大特點(diǎn)是訪問(wèn)速度快,但也存在下面的一些缺點(diǎn):
- MySQL 需要讀取表中索引列的值來(lái)參與散列計(jì)算,散列計(jì)算是一個(gè)比較耗時(shí)的操作。也就是說(shuō),相對(duì)于 B- 樹(shù)索引來(lái)說(shuō),建立哈希索引會(huì)耗費(fèi)更多的時(shí)間。
- 不能使用 HASH 索引排序。
- HASH 索引只支持等值比較,如“=”“IN()”或“<=>”。
- HASH 索引不支持鍵的部分匹配,因?yàn)樵谟?jì)算 HASH 值的時(shí)候是通過(guò)整個(gè)索引值來(lái)計(jì)算的。
根據(jù)索引的具體用途,MySQL 中的索引在邏輯上分為以下 5 類(lèi):
1) 普通索引
普通索引是最基本的索引類(lèi)型,唯一任務(wù)是加快對(duì)數(shù)據(jù)的訪問(wèn)速度,沒(méi)有任何限制。創(chuàng)建普通索引時(shí),通常使用的關(guān)鍵字是 INDEX 或 KEY。
2) 唯一性索引
唯一性索引是不允許索引列具有相同索引值的索引。如果能確定某個(gè)數(shù)據(jù)列只包含彼此各不相同的值,在為這個(gè)數(shù)據(jù)列創(chuàng)建索引的時(shí)候就應(yīng)該用關(guān)鍵字 UNIQUE 把它定義為一個(gè)唯一性索引。
創(chuàng)建唯一性索引的目的往往不是為了提高訪問(wèn)速度,而是為了避免數(shù)據(jù)出現(xiàn)重復(fù)。
3)?主鍵索引
主鍵索引是一種唯一性索引,即不允許值重復(fù)或者值為空,并且每個(gè)表只能有一個(gè)主鍵。主鍵可以在創(chuàng)建表的時(shí)候指定,也可以通過(guò)修改表的方式添加,必須指定關(guān)鍵字 PRIMARY KEY。
注意:主鍵是數(shù)據(jù)庫(kù)考察的重點(diǎn)。注意每個(gè)表只能有一個(gè)主鍵。
4) 空間索引
空間索引主要用于地理空間數(shù)據(jù)類(lèi)型 GEOMETRY。
5) 全文索引
全文索引只能在 VARCHAR 或 TEXT 類(lèi)型的列上創(chuàng)建,并且只能在 MyISAM 表中創(chuàng)建。
索引在邏輯上分為以上 5 類(lèi),但在實(shí)際使用中,索引通常被創(chuàng)建成單列索引和組合索引。
- 單列索引就是索引只包含原表的一個(gè)列。
- 組合索引也稱(chēng)為復(fù)合索引或多列索引,相對(duì)于單列索引來(lái)說(shuō),組合索引是將原表的多個(gè)列共同組成一個(gè)索引。
提示:一個(gè)表可以有多個(gè)單列索引,但這些索引不是組合索引。一個(gè)組合索引實(shí)質(zhì)上為表的查詢(xún)提供了多個(gè)索引,以此來(lái)加快查詢(xún)速度。比如,在一個(gè)表中創(chuàng)建了一個(gè)組合索引(c1,c2,c3),在實(shí)際查詢(xún)中,系統(tǒng)用來(lái)實(shí)際加速的索引有三個(gè):單個(gè)索引(c1)、雙列索引(c1,c2)和多列索引(c1,c2,c3)。
為了提高索引的應(yīng)用性能,MySQL中的索引可以根據(jù)具體應(yīng)用采用不同的索引策略。這些索引策略所對(duì)應(yīng)的索引類(lèi)型有聚集索引、次要索引、覆蓋索引、復(fù)合索引、前綴索引、唯一索引等。
索引的使用原則和注意事項(xiàng)
雖然索引可以加快查詢(xún)速度,提高 MySQL 的處理性能,但是過(guò)多地使用索引也會(huì)造成以下弊端:
- 創(chuàng)建索引和維護(hù)索引要耗費(fèi)時(shí)間,這種時(shí)間隨著數(shù)據(jù)量的增加而增加。
- 除了數(shù)據(jù)表占數(shù)據(jù)空間之外,每一個(gè)索引還要占一定的物理空間。如果要建立聚簇索引,那么需要的空間就會(huì)更大。
- 當(dāng)對(duì)表中的數(shù)據(jù)進(jìn)行增加、刪除和修改的時(shí)候,索引也要?jiǎng)討B(tài)地維護(hù),這樣就降低了數(shù)據(jù)的維護(hù)速度。
注意:索引可以在一些情況下加速查詢(xún),但是在某些情況下,會(huì)降低效率。
索引只是提高效率的一個(gè)因素,因此在建立索引的時(shí)候應(yīng)該遵循以下原則:
- 在經(jīng)常需要搜索的列上建立索引,可以加快搜索的速度。
- 在作為主鍵的列上創(chuàng)建索引,強(qiáng)制該列的唯一性,并組織表中數(shù)據(jù)的排列結(jié)構(gòu)。
- 在經(jīng)常使用表連接的列上創(chuàng)建索引,這些列主要是一些外鍵,可以加快表連接的速度。
- 在經(jīng)常需要根據(jù)范圍進(jìn)行搜索的列上創(chuàng)建索引,因?yàn)樗饕呀?jīng)排序,所以其指定的范圍是連續(xù)的。
- 在經(jīng)常需要排序的列上創(chuàng)建索引,因?yàn)樗饕呀?jīng)排序,所以查詢(xún)時(shí)可以利用索引的排序,加快排序查詢(xún)。
- 在經(jīng)常使用 WHERE 子句的列上創(chuàng)建索引,加快條件的判斷速度。
與此對(duì)應(yīng),在某些應(yīng)用場(chǎng)合下建立索引不能提高 MySQL 的工作效率,甚至在一定程度上還帶來(lái)負(fù)面效應(yīng),降低了數(shù)據(jù)庫(kù)的工作效率,一般來(lái)說(shuō)不適合創(chuàng)建索引的環(huán)境如下:
- 對(duì)于那些在查詢(xún)中很少使用或參考的列不應(yīng)該創(chuàng)建索引。因?yàn)檫@些列很少使用到,所以有索引或者無(wú)索引并不能提高查詢(xún)速度。相反,由于增加了索引,反而降低了系統(tǒng)的維護(hù)速度,并增大了空間要求。
- 對(duì)于那些只有很少數(shù)據(jù)值的列也不應(yīng)該創(chuàng)建索引。已經(jīng)為大家精心準(zhǔn)備了大數(shù)據(jù)的系統(tǒng)學(xué)習(xí)資料,從Linux-Hadoop-spark-......,需要的小伙伴可以點(diǎn)擊因?yàn)檫@些列的取值很少,例如人事表的性別列。查詢(xún)結(jié)果集的數(shù)據(jù)行占了表中數(shù)據(jù)行的很大比例,增加索引并不能明顯加快檢索速度。
- 對(duì)于那些定義為 TEXT、IMAGE 和 BIT 數(shù)據(jù)類(lèi)型的列不應(yīng)該創(chuàng)建索引。因?yàn)檫@些列的數(shù)據(jù)量要么相當(dāng)大,要么取值很少。
- 當(dāng)修改性能遠(yuǎn)遠(yuǎn)大于檢索性能時(shí),不應(yīng)該創(chuàng)建索引。因?yàn)樾薷男阅芎蜋z索性能是互相矛盾的。當(dāng)創(chuàng)建索引時(shí),會(huì)提高檢索性能,降低修改性能。當(dāng)減少索引時(shí),會(huì)提高修改性能,降低檢索性能。因此,當(dāng)修改性能遠(yuǎn)遠(yuǎn)大于檢索性能時(shí),不應(yīng)該創(chuàng)建索引。
總結(jié)
- 上一篇: MySQL修改和删除触发器(DROP T
- 下一篇: MySQL创建索引(CREATE IND