mysql的索引是存儲(chǔ)引擎實(shí)現(xiàn)的磕道,而不是服務(wù)層實(shí)現(xiàn)的,沒(méi)有統(tǒng)一的標(biāo)準(zhǔn)入桂,不同的引擎支持的索引類型不太一樣也不一定支持所有的索引份名,即使同一種索引不同的引擎實(shí)現(xiàn)方式也不一定一樣
索引類型
B-Tree索引
最常見(jiàn)的一種索引,不同的引擎以不同的方式使用B-Tree(B+,T-Tree索引)租副,性能也各有不同坐慰,各有優(yōu)劣。
BTree對(duì)索引是按順序存儲(chǔ)的用僧,很適合查找范圍數(shù)據(jù)结胀,索引對(duì)多個(gè)值排序的依據(jù)是定義索引的時(shí)候列的順序可以使用BTree的索引查詢類型:全鍵值,鍵值范圍查詢责循,列前綴匹配糟港。BTree索引的劣勢(shì)必須最左列匹配,不能跳過(guò)中間的列院仿,如果某一個(gè)列有范圍匹配秸抚,則該列右邊的列的索引無(wú)法生效
哈希索引
只有memory引擎顯示支持哈希索引,哈希索引只能進(jìn)行精確匹配歹垫。哈希索引可以用來(lái)壓縮索引列的長(zhǎng)度如:一個(gè)url壓縮成一個(gè)64位的int大大減少索引字段的空間
全文索引
全文索引是用來(lái)匹配文本關(guān)鍵字的類似于搜索引擎
空間索引(R-Tree)
用來(lái)存儲(chǔ)地理位置信息的剥汤,不同于其他索引列,從各個(gè)維度用來(lái)進(jìn)行索引
其他索引(TokuDB的分形樹(shù))
一種新的數(shù)據(jù)結(jié)構(gòu)排惨,既有BTree的優(yōu)點(diǎn)吭敢,又避免了BTree的缺點(diǎn)
高性能索引
獨(dú)立索引
索引列不能是表達(dá)式的一部分,假設(shè) tablea 的列columa上有獨(dú)立的索引,則如下查詢:
select * from tablea where columna+1=333 ,不能使用該索引暮芭,因?yàn)?(columna+1) 為表達(dá)式省有,mysql無(wú)法自動(dòng)解析,查詢時(shí)盡量簡(jiǎn)化where語(yǔ)句谴麦,將索引列單獨(dú)放置到比較符號(hào)的一側(cè)
前綴索引和索引選擇性
有時(shí)候需要索引很長(zhǎng)的字符串蠢沿,這會(huì)使索引非常慢,一種辦法是受用哈希對(duì)字符串進(jìn)行瘦身匾效,有時(shí)候這種做法還不夠舷蟀,通常可以索引開(kāi)始的部分字符串而不是全部
多列索引
常見(jiàn)的錯(cuò)誤是為每個(gè)列創(chuàng)建索引或按錯(cuò)誤的順序創(chuàng)建多列索引面哼,再多個(gè)列上創(chuàng)建單獨(dú)的索引大多數(shù)情況下并不能提高mysql的性能j(5.0之后的索引合并策略野宜,一定程度上可以緩解),向下面的例子魔策,在film_id和actor_id上各有一個(gè)單列索引匈子,對(duì)于如下查詢都不是好的選擇: select film_id,actor_id from tableA where actor_id=1 or film_id=2
選擇合適的索引順序
在一個(gè)多列BTree索引中,索引列的順序意味著索引先按照最左列進(jìn)行排序闯袒,其次是第二列虎敦,等等游岳。一個(gè)經(jīng)驗(yàn)法則是將選擇性最高的列放到索引的最前列,但通常不如避免隨機(jī)I/O,和排序那么重要其徙∨咂龋可能還依賴于值得分布,和查詢的運(yùn)行頻率來(lái)調(diào)整索引列
聚簇索引
聚簇索引不是一種索引類型唾那,而是一種數(shù)據(jù)存儲(chǔ)的方式 访锻,具體的細(xì)節(jié)依賴其實(shí)現(xiàn)方式。 innodb會(huì)給主鍵生成聚簇索引闹获,如果主鍵不存在期犬,會(huì)將第一個(gè)非Null 的unique_key當(dāng)做聚簇索引,如果沒(méi)有unique_key則會(huì)生成一個(gè)隱藏的聚簇索引避诽,innodb中聚簇索引是和存放于葉節(jié)點(diǎn)當(dāng)中的龟虎。
- 優(yōu)點(diǎn)
可以把相關(guān)數(shù)據(jù)存放在一起,例如根據(jù)用戶Id來(lái)聚集數(shù)據(jù)茎用,這樣加載用戶數(shù)據(jù)的時(shí)候遣总,只需從磁盤讀取少數(shù)頁(yè)就到獲取到聚集的某個(gè)用戶的所有數(shù)據(jù)睬罗,否則可能導(dǎo)致每讀取一條數(shù)據(jù)轨功,發(fā)生一次磁盤IO
數(shù)據(jù)訪問(wèn)速度更快,聚簇索引將數(shù)據(jù)和索引存放在一起容达,通常比非聚簇索引更快
使用覆蓋索引掃描的查詢可以直接使用頁(yè)節(jié)點(diǎn)的中主鍵值 - 缺點(diǎn)
插入速度嚴(yán)重依賴于插入順序古涧,按照主鍵的順序插入,是加載數(shù)據(jù)到innodb中最快的方式花盐,如果不是按順序插入羡滑,最好加載完成后執(zhí)行一次optimize_table命令重新組織下表。
更新聚簇索引列的代價(jià)很高算芯,強(qiáng)制被更新的行移動(dòng)到新的位置
在插入新行或主鍵更新導(dǎo)致需要移動(dòng)行的時(shí)候柒昏,面臨也分裂(一行數(shù)據(jù)存儲(chǔ)到2個(gè)頁(yè)中)
導(dǎo)致全表掃描變慢,特別是行比較稀疏的時(shí)候熙揍,或頁(yè)分裂導(dǎo)致數(shù)據(jù)不一致的時(shí)候
innodb中主鍵遞增的插入职祷,可以避免隨機(jī)IO的發(fā)生,但是高并發(fā)的情況下卻會(huì)造成主鍵的上界熱點(diǎn)届囚,因?yàn)樗械牟迦攵及l(fā)生再這里有梆,如何解決?
覆蓋索引:
如果一個(gè)索引包含所有需要查詢的字段意系,也就沒(méi)必要再去查詢表了泥耀,則稱之為覆蓋索引,覆蓋索引是非常有用的工具蛔添,可以極大的提高性能痰催,因?yàn)樗饕谴嬖谟趦?nèi)存中(數(shù)據(jù)不一定兜辞,innodb因?yàn)榫鄞厮饕拇嬖冢琈yisam內(nèi)存中只存索引)
冗余和重復(fù)索引
1. 重復(fù)索引
重復(fù)索引是指完全相同(列順序陨囊,和索引類型都完全相同)的索引弦疮,mysql的主鍵限制和唯一限制是通過(guò)索引實(shí)現(xiàn)的,mysql允許創(chuàng)建重復(fù)索引蜘醋,但是通常沒(méi)有理由這么做胁塞。
2. 冗余索引
冗余索引和重復(fù)索引有一些不同,索引A,是索引(A,B)的冗余索引(兩者索引類型相同)压语;索引B不是索引(A,B)的索引啸罢。大部分時(shí)候不需要冗余索引,應(yīng)該擴(kuò)展已有的索引而不是胎食,新增加索引扰才,有時(shí)候也有例外,例如擴(kuò)展新的索引導(dǎo)致索引太大了厕怜,導(dǎo)致使用該索引的其他查詢性能問(wèn)題衩匣,例如
如果在整數(shù)列上存在一個(gè)索引,現(xiàn)在需要額外增加一個(gè)很長(zhǎng)的varchar列擴(kuò)展該索引粥航,那性能可能回急劇下降琅捏,特別是查詢把這個(gè)索引當(dāng)做覆蓋查詢或者表是myisam表而且有很多范圍查詢的時(shí)候(myisam前綴壓縮)