MySQL数据库索引
目錄
索引是什么
索引有哪些結(jié)構(gòu)/索引常見(jiàn)的模型
B+樹(shù)索引
數(shù)據(jù)庫(kù)有哪些索引
唯一索引
聚簇索引與非聚簇索引
全文索引
索引的最左前綴原則
索引下推
使用索引一定能提高查詢(xún)性能嗎?
哪些情況下設(shè)置了索引但是無(wú)法使用
哪些情況下需要設(shè)置索引、哪些情況下不需要
什么情況下應(yīng)該使用組合/聯(lián)合索引而非單獨(dú)索引
MySQL中索引是如何組織數(shù)據(jù)的存儲(chǔ)的
Mysql索引原理
Mysql是如何根據(jù)索引查詢(xún)數(shù)據(jù)的
普通索引和唯一索引,應(yīng)該怎么選擇?
索引是什么
索引是對(duì)數(shù)據(jù)庫(kù)表中一個(gè)或多個(gè)列的值進(jìn)行排序的結(jié)構(gòu),是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)
你也可以這樣理解:索引就是加快檢索表中數(shù)據(jù)的方法。數(shù)據(jù)庫(kù)的索引類(lèi)似于書(shū)籍的索引。在書(shū)籍中,索引允許用戶(hù)不必翻閱完整本書(shū)就能迅速地找到所需要的信息。在數(shù)據(jù)庫(kù)中,索引也允許數(shù)據(jù)庫(kù)程序迅速地找到表中的數(shù)據(jù),而不必掃描整個(gè)數(shù)據(jù)庫(kù)。
MySQL數(shù)據(jù)庫(kù)幾個(gè)基本的索引類(lèi)型:普通索引、唯一索引、主鍵索引、全文索引
1.索引加快數(shù)據(jù)庫(kù)的檢索速度
2.索引降低了插入、刪除、修改等維護(hù)任務(wù)的速度
3.唯一索引可以確保每一行數(shù)據(jù)的唯一性
4.通過(guò)使用索引,可以在查詢(xún)的過(guò)程中使用優(yōu)化隱藏器,提高系統(tǒng)的性能
5.索引需要占物理和數(shù)據(jù)空間
索引有哪些結(jié)構(gòu)/索引常見(jiàn)的模型
1. 哈希表:一種以鍵-值(key-value)存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu),我們只要輸入待查找的值即key,就可以找到其對(duì)應(yīng)的值即Value。哈希的思路很簡(jiǎn)單,把值放在數(shù)組里,用一個(gè)哈希函數(shù)把key換算成一個(gè)確定的位置,然后把value放在數(shù)組的這個(gè)位置。如果出現(xiàn)hash沖突,則在沖突的value位置使用鏈表進(jìn)行連接。
? ? 適用場(chǎng)景:等值查詢(xún),如Memcached及其他一些NoSQL引擎
? ??
2.?有序數(shù)組
? ? 適用場(chǎng)景:只適用于靜態(tài)存儲(chǔ)引擎。用于等值查詢(xún)和范圍查詢(xún)(ID值必須是遞增的)
? ??
3. 搜索樹(shù):左子節(jié)點(diǎn)小于父節(jié)點(diǎn)、父節(jié)點(diǎn)小于右子節(jié)點(diǎn)。Innodb使用B+樹(shù),為什么數(shù)據(jù)庫(kù)使用B+樹(shù)作為索引?
問(wèn):為什么采用B+樹(shù)?這和Hash索引比較起來(lái)有什么優(yōu)缺點(diǎn)嗎?
答:因?yàn)镠ash索引底層是哈希表,哈希表是一種以key-value存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu),所以多個(gè)數(shù)據(jù)在存儲(chǔ)關(guān)系上是完全沒(méi)有任何順序關(guān)系的,所以,對(duì)于區(qū)間查詢(xún)是無(wú)法直接通過(guò)索引查詢(xún)的,就需要全表掃描。所以,哈希索引只適用于等值查詢(xún)的場(chǎng)景。而B(niǎo)+樹(shù)是一種多路平衡查詢(xún)樹(shù),所以他的節(jié)點(diǎn)是天然有序的(左子節(jié)點(diǎn)小于父節(jié)點(diǎn)、父節(jié)點(diǎn)小于右子節(jié)點(diǎn)),所以對(duì)于范圍查詢(xún)的時(shí)候不需要做全表掃描
1、哈希索引適合等值查詢(xún),但是無(wú)法進(jìn)行范圍查詢(xún)?
2、哈希索引沒(méi)辦法利用索引完成排序?
3、哈希索引不支持多列聯(lián)合索引的最左匹配規(guī)則?
4、如果有大量重復(fù)鍵值的情況下,哈希索引的效率會(huì)很低,因?yàn)榇嬖诠E鲎矄?wèn)題
B+樹(shù)索引
我們舉個(gè)例子,假設(shè)我們有一個(gè)主鍵列為ID的表,表中有字段k,并且在k上有索引。
表中R1~R5的(ID,k)值分別為(100,1)、(200,2)、(300,3)、(500,5)和(600,6),兩棵樹(shù)的示例示意圖如下。
主鍵索引的葉子節(jié)點(diǎn)存的是整行數(shù)據(jù)。在InnoDB里,主鍵索引也被稱(chēng)為聚簇索引(clustered index)。
非主鍵索引的葉子節(jié)點(diǎn)內(nèi)容是主鍵的值。在InnoDB里,非主鍵索引也被稱(chēng)為二級(jí)索引(secondary index)。
? ? PS:主鍵長(zhǎng)度越小,普通索引的葉子節(jié)點(diǎn)就越小,普通索引占用的空間也就越小。
基于主鍵索引和普通索引的查詢(xún)有什么區(qū)別?
- 如果語(yǔ)句是select * from T where ID=500,即主鍵查詢(xún)方式,則只需要搜索ID這棵B+樹(shù);
- 如果語(yǔ)句是select * from T where k=5,即普通索引查詢(xún)方式,則需要先搜索k索引樹(shù),得到ID的值為500,再到ID索引樹(shù)搜索一次。這個(gè)過(guò)程稱(chēng)為回表。
也就是說(shuō),基于非主鍵索引的查詢(xún)需要多掃描一棵索引樹(shù)。因此,我們?cè)趹?yīng)用中應(yīng)該盡量使用主鍵查詢(xún)。
索引維護(hù)
? ? 對(duì)于主鍵不是遞增的表,在插入數(shù)據(jù)時(shí),如新插入數(shù)據(jù)ID值為400,則需要邏輯上挪動(dòng)后面的數(shù)據(jù),空出位置。
? ? 而更糟的情況是,如果R5所在的數(shù)據(jù)頁(yè)已經(jīng)滿(mǎn)了,根據(jù)B+樹(shù)的算法,這時(shí)候需要申請(qǐng)一個(gè)新的數(shù)據(jù)頁(yè),然后挪動(dòng)部分?jǐn)?shù)據(jù)過(guò)去。這個(gè)過(guò)程稱(chēng)為頁(yè)分裂。
? ? 除了性能外,頁(yè)分裂操作還影響數(shù)據(jù)頁(yè)的利用率。原本放在一個(gè)頁(yè)的數(shù)據(jù),現(xiàn)在分到兩個(gè)頁(yè)中,整體空間利用率降低大約50%。當(dāng)
? ? 然有分裂就有合并。當(dāng)相鄰兩個(gè)頁(yè)由于刪除了數(shù)據(jù),利用率很低之后,會(huì)將數(shù)據(jù)頁(yè)做合并。合并的過(guò)程,可以認(rèn)為是分裂過(guò)程的逆過(guò)程。
數(shù)據(jù)庫(kù)有哪些索引
在MySql數(shù)據(jù)庫(kù)中,有四種索引:聚集索引(主鍵索引)(聚簇索引)、普通索引、唯一索引以及全文索引(FUNLLTEXT INDEX)
索引又可分為聚簇索引和非聚簇索引兩種
唯一索引
一種索引,不允許具有索引值相同的行,從而禁止重復(fù)的索引或鍵值。系統(tǒng)在創(chuàng)建該索引時(shí)檢查是否有重復(fù)的鍵值,并在每次使用 INSERT 或 UPDATE 語(yǔ)句添加數(shù)據(jù)時(shí)進(jìn)行檢查。
CREATE UNIQUE CLUSTERED INDEX myclumn_cindex ON mytable(mycolumn)
聚簇索引與非聚簇索引
可以理解為主鍵索引與普通索引
| 聚簇索引:是對(duì)磁盤(pán)上實(shí)際數(shù)據(jù)重新組織以按指定的一個(gè)或多個(gè)列的值排序的算法。特點(diǎn)是存儲(chǔ)數(shù)據(jù)的順序和索引順序一致,且一個(gè)表只能有一個(gè)聚簇索引,因?yàn)槲锢泶鎯?chǔ)只能有一個(gè)順序。主鍵索引一般都是聚簇索引 非聚簇索引:表數(shù)據(jù)存儲(chǔ)順序與索引順序無(wú)關(guān)。對(duì)于非聚簇索引,葉結(jié)點(diǎn)包含索引字段值及指向數(shù)據(jù)頁(yè)數(shù)據(jù)行的邏輯指針,其行數(shù)量與數(shù)據(jù)表行數(shù)據(jù)量一致。非聚簇索引記錄的物理順序與邏輯順序沒(méi)有必然的聯(lián)系,與數(shù)據(jù)的存儲(chǔ)物理結(jié)構(gòu)沒(méi)有關(guān)系;一個(gè)表對(duì)應(yīng)的非聚簇索引可以有多條,根據(jù)不同列的約束可以建立不同要求的非聚簇索引; 一般情況下主鍵會(huì)默認(rèn)創(chuàng)建聚簇索引,且一張表只允許存在一個(gè)聚簇索引。因?yàn)槲锢泶鎯?chǔ)只能有一個(gè)順序。 聚簇索引的葉子節(jié)點(diǎn)就是數(shù)據(jù)節(jié)點(diǎn)(Innodb的B+樹(shù)的主鍵對(duì)應(yīng)的數(shù)據(jù)節(jié)點(diǎn)),而非聚簇索引的葉子節(jié)點(diǎn)仍然是索引節(jié)點(diǎn),只不過(guò)有指向?qū)?yīng)數(shù)據(jù)塊的指針。 聚簇索引主鍵的插入速度要比非聚簇索引主鍵的插入速度慢很多。 相比之下,聚簇索引適合排序,非聚簇索引不適合用在排序的場(chǎng)合。因?yàn)榫鄞厮饕旧硪呀?jīng)是按照物理順序放置的,排序很快。非聚簇索引則沒(méi)有按序存放,需要額外消耗資源來(lái)排序。 建立聚簇索引的語(yǔ)句: CREATE CLUSTER INDEX index_name ON table_name(column_name1,...); |
問(wèn):主鍵索引查詢(xún)只會(huì)查一次,而非主鍵索引一定需要回表查詢(xún)多次嗎?
答:通過(guò)覆蓋索引也可以只查詢(xún)一次
覆蓋索引(covering index)指一個(gè)查詢(xún)語(yǔ)句的執(zhí)行只用從索引中就能夠取得,不必從數(shù)據(jù)表中讀取。也可以稱(chēng)之為實(shí)現(xiàn)了索引覆蓋。
當(dāng)一條查詢(xún)語(yǔ)句符合覆蓋索引條件時(shí),MySQL只需要通過(guò)索引就可以返回查詢(xún)所需要的數(shù)據(jù),這樣避免了查到索引后再返回表操作,減少I(mǎi)/O提高效率。
如,表covering_index_sample中有一個(gè)普通索引 idx_key1_key2(key1,key2)。
當(dāng)我們通過(guò)SQL語(yǔ)句:select key2 from covering_index_sample where key1 = 'keytest';的時(shí)候,就可以通過(guò)覆蓋索引查詢(xún),無(wú)需回表。
注:如果這個(gè)覆蓋索引是一個(gè)前綴索引,那么它依然需要回表,因?yàn)橄到y(tǒng)并不確定前綴索引的定義是否截?cái)嗔送暾畔ⅰ?/p>
問(wèn):以下重建索引的步驟是否存在問(wèn)題?
重建普通索引 k
alter table T drop index k; alter table T add index(k);重建主鍵索引
alter table T drop primary key; alter table T add primary key(id);答:重建索引k的做法是合理的,可以達(dá)到省空間的目的。但是,重建主鍵的過(guò)程不合理。不論是刪除主鍵還是創(chuàng)建主鍵,都會(huì)將整個(gè)表重建。所以連著執(zhí)行這兩個(gè)語(yǔ)句的話(huà),第一個(gè)語(yǔ)句就白做了。這兩個(gè)語(yǔ)句,可以用這個(gè)語(yǔ)句代替 : alter table T engine=InnoDB。
全文索引
| 全文索引(也稱(chēng)全文檢索)是目前搜索引擎使用的一種關(guān)鍵技術(shù)。它能夠利用【分詞技術(shù)】等多種算法智能分析出文本文字中關(guān)鍵詞的頻率和重要性,然后按照一定的算法規(guī)則智能地篩選出我們想要的搜索結(jié)果。 select * from 表名 where?標(biāo)題 like '%xxx%' or 內(nèi)容?like '%xxx%' or 作者?like '%xxx%'; 這種搜索效率無(wú)比底下 全文索引是為了使得“關(guān)鍵詞搜索”功能更加的高效能。 我們有這么一張數(shù)據(jù)表:? 文章id 文章標(biāo)題 文章內(nèi)容 1 超級(jí)塞亞人 ?我是超級(jí)塞亞人我喜歡吃蘋(píng)果,我不是233大國(guó)的人,也不是地球人 2 我233大國(guó)威武,我233大國(guó)13億人,我233大國(guó) 3 我喜歡游泳 游泳有很多好方法 4 動(dòng)畫(huà)片 我兒子喜歡看動(dòng)畫(huà)片,尤其是七龍珠,因?yàn)槔锩嬗腥麃喨?#xff0c;而且塞亞人喜歡吃蘋(píng)果,他們不是地球人 5 運(yùn)動(dòng) 我喜歡運(yùn)動(dòng),喜歡跑步,喜歡游泳,喜歡健身,喜歡xxoo 6 打炮 我是一個(gè)二戰(zhàn)的老兵,這是我的回憶錄,我最幸福的時(shí)光就是在233大國(guó)吃著蘋(píng)果打炮 7 。。。 ? 8 。。。 ? 9 。。。 ? 然后,根據(jù)以上的文章內(nèi)容,如果建立了一個(gè)索引文件(這里忽略索引文件的數(shù)據(jù)結(jié)構(gòu),僅僅以一種易于理解的方式呈現(xiàn)):? 關(guān)鍵詞 ? 文章id 塞亞人 ? ?1,4 蘋(píng)果 ? ? ?1,4,6 233大國(guó) ? ? ?1,2,6 地球 ? ? ? ?1,4 游泳 ? ? ? ?3,5 七龍珠 ? ? ?4 喜歡 ? ? 1,4,5,6 ?? 那么當(dāng)我想搜索 ?“塞亞人”的時(shí)候,這個(gè)索引文件直接告訴我在文章id為1和4的文章里有這個(gè)詞。? 這個(gè)索引文件就是“全文索引”。 如何使用全文索引和分詞的方式來(lái)幫助優(yōu)化你的搜索呢? 需要工作的程序:索引程序,分詞程序,數(shù)據(jù)庫(kù)。? 工作原理:? 1、索引程序從數(shù)據(jù)庫(kù)讀取數(shù)據(jù),比如上面例子中的數(shù)據(jù)表,索引程序通過(guò)sql語(yǔ)句:select 文章id,文章標(biāo)題,文章內(nèi)容 from 文章表.獲得文章的相關(guān)數(shù)據(jù)? 2、索引程序?qū)π枰饕膬?nèi)容進(jìn)行“分詞”,而這里的分詞就是調(diào)用分詞程序啦!? 3、索引程序?qū)Ψ趾迷~的一個(gè)個(gè)詞條加入索引文件。 在你寫(xiě)的代碼里,原來(lái)到數(shù)據(jù)庫(kù)----like %xxx%-----的語(yǔ)句就變成了到索引文件里去查找,從而找到相應(yīng)的數(shù)據(jù)(這點(diǎn)相信你已經(jīng)理解啦!) 創(chuàng)建全文索引的兩種方法: 1.在建表語(yǔ)句中 2.在已知表中 ALTER TABLE article ADD FULLTEXT INDEX fulltext_article(title,content); 具體如何使用全文索引呢? 不用全文索引時(shí)的寫(xiě)法:SELECT * FROM article WHERE content LIKE ‘%查詢(xún)字符串%’; 使用全文索引:SELECT * FROM article WHERE MATCH(title,content) AGAINST (‘查詢(xún)字符串’); 注意: 1、MySql自帶的全文索引只能對(duì)英文進(jìn)行全文檢索,目前無(wú)法對(duì)中文進(jìn)行全文檢索。如果需要對(duì)包含中文在內(nèi)的文本數(shù)據(jù)進(jìn)行全文檢索,我們需要采用Sphinx(斯芬克斯)/Coreseek技術(shù)來(lái)處理中文。 2、使用MySql自帶的全文索引時(shí),如果查詢(xún)字符串的長(zhǎng)度過(guò)短將無(wú)法得到期望的搜索結(jié)果。MySql全文索引所能找到的詞默認(rèn)最小長(zhǎng)度為4個(gè)字符。另外,如果查詢(xún)的字符串包含停止詞,那么該停止詞將會(huì)被忽略。 3、如果可能,請(qǐng)盡量先創(chuàng)建表并插入所有數(shù)據(jù)后再創(chuàng)建全文索引,而不要在創(chuàng)建表時(shí)就直接創(chuàng)建全文索引,因?yàn)榍罢弑群笳叩娜乃饕室摺?/p> |
索引的最左前綴原則
在MySQL建立聯(lián)合索引時(shí)會(huì)遵守最左前綴匹配原則,即最左優(yōu)先,在檢索數(shù)據(jù)時(shí)從聯(lián)合索引的最左邊開(kāi)始匹配。
索引下推
Index Condition Pushdown (ICP) ,Mysql 5.6添加,用于優(yōu)化數(shù)據(jù)查詢(xún)。
索引條件下推優(yōu)化可以減少存儲(chǔ)引擎查詢(xún)基礎(chǔ)表的次數(shù),也可以減少M(fèi)ySQL服務(wù)器從存儲(chǔ)引擎接收數(shù)據(jù)的次數(shù)。?
用下面這種場(chǎng)景進(jìn)行介紹
假設(shè)有如下查詢(xún)語(yǔ)句:select * from tuser where name like '張%' and age=10 and ismale=1;? (有聯(lián)合索引 name,age)
我們知道了前綴索引規(guī)則,所以這個(gè)語(yǔ)句在搜索索引樹(shù)的時(shí)候,只能用 “張”
以下是Mysql 5.6 之前的查詢(xún)流程:
以下是Mysql 5.6 時(shí)的查詢(xún)流程:(使用了索引下推)
InnoDB在(name,age)索引內(nèi)部就判斷了age是否等于10,對(duì)于不等于10的記錄,直接判斷并跳過(guò)。在我們的這個(gè)例子中,只需要對(duì)ID4、ID5這兩條記錄回表取數(shù)據(jù)判斷,就只需要回表2次。
使用索引一定能提高查詢(xún)性能嗎?
通常,通過(guò)索引查詢(xún)數(shù)據(jù)比全表掃描要快,但是我們也必須注意到它的代價(jià).
索引需要空間來(lái)存儲(chǔ),也需要定期維護(hù), 每當(dāng)有記錄在表中增減或索引列被修改時(shí),索引本身也會(huì)被修改。這意味著每條記錄的INSERT,DELETE,UPDATE將為此多付出4,5次的磁盤(pán)I/O.
索引不但會(huì)使得插入和修改的效率降低,而且在查詢(xún)的時(shí)候,有一個(gè)查詢(xún)優(yōu)化器,太多的索引會(huì)讓優(yōu)化器困惑,可能沒(méi)有辦法找到正確的查詢(xún)路徑,從而選擇了慢的索引。
索引范圍查詢(xún)(INDEX RANGE SCAN)適用于兩種情況:
? ? 1.基于一個(gè)范圍的檢索,一般查詢(xún)返回結(jié)果集小于表中記錄數(shù)的30%
? ? 2.基于非唯一性索引的檢索
? ? 3.直接晉升為覆蓋索引,避免多次查表
哪些情況下設(shè)置了索引但是無(wú)法使用
根本原因是查詢(xún)優(yōu)化器決定不使用索引:
一條SQL語(yǔ)句的查詢(xún),可以有不同的執(zhí)行方案,至于最終選擇哪種方案,需要通過(guò)優(yōu)化器進(jìn)行選擇,選擇執(zhí)行成本最低的方案。在一條單表查詢(xún)語(yǔ)句真正執(zhí)行之前,MySQL的查詢(xún)優(yōu)化器會(huì)找出執(zhí)行該語(yǔ)句所有可能使用的方案,對(duì)比之后找出成本最低的方案。這個(gè)成本最低的方案就是所謂的執(zhí)行計(jì)劃。優(yōu)化過(guò)程大致如下:
1、根據(jù)搜索條件,找出所有可能使用的索引?
2、計(jì)算全表掃描的代價(jià)?
3、計(jì)算使用不同索引執(zhí)行查詢(xún)的代價(jià)?
4、對(duì)比各種執(zhí)行方案的代價(jià),找出成本最低的那一個(gè)
有時(shí)候查詢(xún)語(yǔ)句沒(méi)有按照索引的要求來(lái)也會(huì)導(dǎo)致無(wú)法使用索引,如下:
哪些情況下需要設(shè)置索引、哪些情況下不需要
| 需要: 1).主鍵自動(dòng)建立唯一索引 不需要: 1).表記錄太少 4).where條件里用不到的字段不創(chuàng)建索引 |
什么情況下應(yīng)該使用組合/聯(lián)合索引而非單獨(dú)索引
| 假設(shè)有條件語(yǔ)句A=a AND B=b,如果A和B是兩個(gè)單獨(dú)的索引,在AND條件下只有一個(gè)索引起作用,對(duì)于B則要逐個(gè)判斷,而如果使用組合索引(A, B),只要遍歷一棵樹(shù)就可以了,大大增加了效率。但是對(duì)于A=a OR B=b,由于是 或 的關(guān)系,因而組合索引是不起作用的,此時(shí)可以使用單獨(dú)索引,這個(gè)時(shí)候,兩個(gè)索引可以同時(shí)起作用。 在建立聯(lián)合索引的時(shí)候,如何安排索引內(nèi)的字段順序? ? ? 評(píng)估標(biāo)準(zhǔn)是:索引的復(fù)用能力。因?yàn)榭梢灾С肿钭笄熬Y,所以當(dāng)已經(jīng)有了(a,b)這個(gè)聯(lián)合索引后,一般就不需要單獨(dú)在a上建立索引了。 ? ? 因此,第一原則是,如果通過(guò)調(diào)整順序,可以少維護(hù)一個(gè)索引,那么這個(gè)順序往往就是需要優(yōu)先考慮采用的。 ? ? 那么,如果既有聯(lián)合查詢(xún),又有基于a、b各自的查詢(xún)呢?查詢(xún)條件里面只有b的語(yǔ)句,是無(wú)法使用(a,b)這個(gè)聯(lián)合索引的,這時(shí)候你不得不維護(hù)另外一個(gè)索引,也就是說(shuō)你需要同時(shí)維護(hù)(a,b)、(b) 這兩個(gè)索引。 ? ? 這時(shí)候,我們要考慮的原則就是空間了。也就是說(shuō),如果b的大小是比較小的,如boolean、int類(lèi)型, 那么可以再多建立一個(gè)b索引 下面通過(guò)一個(gè)例子來(lái)加深理解 假設(shè)有這么一個(gè)表: CREATE TABLE `geek` ( 有以下經(jīng)常使用的查詢(xún)語(yǔ)句 這里我們需要思考,ca與cb索引是否都是必要的? ? ? 索引 ca 的組織是先按c排序,再按a排序,同時(shí)記錄主鍵(b),根據(jù)最左前綴原則,實(shí)際上,ca索引的功能同c索引的功能是差不多的,因此可以得出ca索引不是必要的 ? ? 索引 cb 的組織是先按c排序,再按b排序,同時(shí)記錄主鍵(a),因此該索引需要保留 |
MySQL中索引是如何組織數(shù)據(jù)的存儲(chǔ)的
| 假如有如下數(shù)據(jù)表: 對(duì)于表中每一行數(shù)據(jù),索引中包含了last_name、first_name、dob列的值,下圖展示了索引是如何組織數(shù)據(jù)存儲(chǔ)的。 可以看到,索引首先根據(jù)第一個(gè)字段來(lái)排列順序,當(dāng)名字相同時(shí),則根據(jù)第三個(gè)字段,即出生日期來(lái)排序,正是因?yàn)檫@個(gè)原因,才有了索引的“最左原則”。 |
普通索引和唯一索引,應(yīng)該怎么選擇?
| 在介紹這兩者的區(qū)別之前,我們先來(lái)介紹change buffer: 什么是change buffer? ? ? 1. 如果數(shù)據(jù)頁(yè)在內(nèi)存中(buffer pool中時(shí))就直接更新 ? ? ? ? ? ?1、從磁盤(pán)讀入數(shù)據(jù)頁(yè)到內(nèi)存(老版本的數(shù)據(jù)頁(yè)); ? ? ? ? ? ?2、從change buffer里找出這個(gè)數(shù)據(jù)頁(yè)的change buffer 記錄(可能有多個(gè)),依次應(yīng)用,得到新版數(shù)據(jù)頁(yè); ? ? ? ? ? ?3、寫(xiě)redo log。這個(gè)redo log包含了數(shù)據(jù)的變更和change buffer的變更。 ? ? 而唯一索引的更新就不能使用 change buffer:對(duì)于唯一索引,所有的更新操作都要先判斷這個(gè)操作是否違反唯一性約束。那么必須將數(shù)據(jù)頁(yè)讀入內(nèi)存才能判斷。比如,要插入(4,400) 這個(gè)記錄,就要先判斷現(xiàn)在表中是否已經(jīng)存在 k=4 的記錄 ? ? 都已經(jīng)讀入內(nèi)存中了,那直接更新內(nèi)存會(huì)更快,沒(méi)有必要使用change buffer了。 ? ? 所以,只有普通索引才能使用change buffer,考慮使用普通索引還是唯一索引,如果能保證不會(huì)數(shù)據(jù)重復(fù),那么最好使用普通索引(可以使用change buffer,且兩類(lèi)索引查詢(xún)能力沒(méi)有區(qū)別) 注意:不是所有的場(chǎng)景用change buffer都能加速: ? ? 1. 設(shè)想一個(gè)對(duì)于寫(xiě)多讀少的業(yè)務(wù)來(lái)說(shuō),change buffer 記錄的變更越多越劃算,例如賬單類(lèi)日志類(lèi) ? ? 2. 反過(guò)來(lái),一個(gè)業(yè)務(wù)的更新模式是寫(xiě)入之后馬上會(huì)做查詢(xún),change buffer里的內(nèi)容不多,由于馬上做查詢(xún)要訪(fǎng)問(wèn)數(shù)據(jù)頁(yè),這樣的io次數(shù)不會(huì)減少 如果某次寫(xiě)入使用了change buffer機(jī)制,之后主機(jī)異常重啟,是否會(huì)丟失change buffer和數(shù)據(jù)? ? ? 雖然寫(xiě)入時(shí)只更新了內(nèi)存,但是在事務(wù)提交的時(shí)候,change buffer的操作也會(huì)記錄到redo log,所以崩潰恢復(fù)的時(shí)候,change buffer也能找回來(lái),即數(shù)據(jù)可以找回來(lái)。 所以普通索引和唯一索引,應(yīng)該怎么選擇? ? ? 查詢(xún)時(shí):兩種索引查詢(xún)性能幾乎沒(méi)差別 ? ? 更新時(shí):大部分場(chǎng)景下,因?yàn)橛衏hange buffer的存在,普通索引的更新速度會(huì)比唯一索引的快(特別適用于寫(xiě)多讀少的場(chǎng)景)(如果所有的更新后面,都馬上伴隨著對(duì)這個(gè)記錄的查詢(xún),那么應(yīng)該關(guān)閉change buffer) |
擴(kuò)展閱讀:
Mysql索引原理https://mp.weixin.qq.com/s/9yeModGuGvDu5S0bW9sU6w
Mysql是如何根據(jù)索引查詢(xún)數(shù)據(jù)的https://mp.weixin.qq.com/s/ymWeGlaBYWYmfogVDFHo5w
總結(jié)
以上是生活随笔為你收集整理的MySQL数据库索引的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 枪毙ctfmon.exe 恢复你的默认输
- 下一篇: 天堂2单机版如何架设mysql_[JAV