最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL數(shù)據(jù)庫(kù)索引的弊端及合理使用

 更新時(shí)間:2021年11月27日 09:01:37   作者:假裝懂編程  
索引可以說(shuō)是數(shù)據(jù)庫(kù)中的一個(gè)大心臟了,如果說(shuō)一個(gè)數(shù)據(jù)庫(kù)少了索引,那么數(shù)據(jù)庫(kù)本身存在的意義就不大了,和普通的文件沒(méi)什么兩樣,本文從細(xì)節(jié)和實(shí)際業(yè)務(wù)的角度看看在MySQL中B+樹索引好處

一個(gè)好的索引對(duì)數(shù)據(jù)庫(kù)系統(tǒng)尤其重要,索引可以說(shuō)是數(shù)據(jù)庫(kù)中的一個(gè)大心臟了,如果說(shuō)一個(gè)數(shù)據(jù)庫(kù)少了索引,那么數(shù)據(jù)庫(kù)本身存在的意義就不大了,和普通的文件沒(méi)什么兩樣。今天來(lái)說(shuō)說(shuō)MySQL索引,從細(xì)節(jié)和實(shí)際業(yè)務(wù)的角度看看在MySQL中B+樹索引好處,以及我們?cè)谑褂盟饕龝r(shí)需要注意的知識(shí)點(diǎn)。

合理利用索引

在工作中,我們可能判斷數(shù)據(jù)表中的一個(gè)字段是不是需要加索引的最直接辦法就是:這個(gè)字段會(huì)不會(huì)經(jīng)常出現(xiàn)在我們的where條件中。從宏觀的角度來(lái)說(shuō),這樣思考沒(méi)有問(wèn)題,但是從長(zhǎng)遠(yuǎn)的角度來(lái)看,有時(shí)可能需要更細(xì)致的思考,比如我們是不是不僅僅需要在這個(gè)字段上建立一個(gè)索引?多個(gè)字段的聯(lián)合索引是不是更好?以一張用戶表為例,用戶表中的字段可能會(huì)有用戶的姓名、用戶的身份證號(hào)、用戶的家庭地址等等。

1.普通索引的弊端

現(xiàn)在有個(gè)需求需要根據(jù)用戶的身份證號(hào)找到用戶的姓名,這時(shí)候很顯然想到的第一個(gè)辦法就是在id_card上建立一個(gè)索引,嚴(yán)格來(lái)說(shuō)是唯一索引,因?yàn)樯矸葑C號(hào)肯定是唯一的,那么當(dāng)我們執(zhí)行以下查詢的時(shí)候:

SELECT name FROM user WHERE id_card=xxx

它的流程應(yīng)該是這樣的:

  • 先在id_card索引樹上搜索,找到id_card對(duì)應(yīng)的主鍵id
  • 通過(guò)id去主鍵索引上搜索,找到對(duì)應(yīng)的name

從效果上來(lái)看,結(jié)果是沒(méi)問(wèn)題的,但是從效率上來(lái)看,似乎這個(gè)查詢有點(diǎn)昂貴,因?yàn)樗鼨z索了兩顆B+樹,假設(shè)一顆樹的高度是3,那么兩顆樹的高度就是6,因?yàn)楦?jié)點(diǎn)在內(nèi)存里(此處兩個(gè)根節(jié)點(diǎn)),所以最終要在磁盤上進(jìn)行IO的次數(shù)是4次,以一次磁盤隨機(jī)IO的時(shí)間平均耗時(shí)是10ms來(lái)說(shuō),那么最終就需要40ms。這個(gè)數(shù)字一般,不算快。

2.主鍵索引的陷阱

既然問(wèn)題是回表,造成了在兩顆樹都檢索了,那么核心問(wèn)題就是看看能不能只在一顆樹上檢索。這里從業(yè)務(wù)的角度你可能發(fā)現(xiàn)了一個(gè)切入點(diǎn),身份證號(hào)是唯一的,那么我們的主鍵是不是可以不用默認(rèn)的自增id了,我們把主鍵設(shè)置成我們的身份證號(hào),這樣整個(gè)表的只需要一個(gè)索引,并且通過(guò)身份證號(hào)可以查到所有需要的數(shù)據(jù)包括我們的姓名,簡(jiǎn)單一想似乎有道理,只要每次插入數(shù)據(jù)的時(shí)候,指定id是身份證號(hào)就行了,但是仔細(xì)一想似乎有問(wèn)題。

這里要從B+樹的特點(diǎn)來(lái)說(shuō),B+樹的數(shù)據(jù)都存在葉子節(jié)點(diǎn)上,并數(shù)據(jù)是頁(yè)式管理的,一頁(yè)是16K,這是什么意思呢?哪怕我們現(xiàn)在是一行數(shù)據(jù),它也要占用16K的數(shù)據(jù)頁(yè),只有當(dāng)我們的數(shù)據(jù)頁(yè)寫滿了之后才會(huì)寫到一個(gè)新的數(shù)據(jù)頁(yè)上,新的數(shù)據(jù)頁(yè)和老的數(shù)據(jù)頁(yè)在物理上不一定是連續(xù)的,而且有一點(diǎn)很關(guān)鍵,雖然數(shù)據(jù)頁(yè)物理上是不連續(xù)的,但是數(shù)據(jù)在邏輯上是連續(xù)的。

也許你會(huì)好奇,這和我們說(shuō)的身份證號(hào)當(dāng)主鍵ID有什么關(guān)系?這時(shí)你應(yīng)該關(guān)注連續(xù)這個(gè)關(guān)鍵字,身份證號(hào)不是連續(xù)的,這意味著什么?當(dāng)我們插入一條不連續(xù)的數(shù)據(jù)的時(shí)候,為了保持連續(xù),需要移動(dòng)數(shù)據(jù),比如原來(lái)在一頁(yè)上的數(shù)據(jù)有1->5,這時(shí)候插入了一條3,那么就需要把5移到3后面,也許你會(huì)說(shuō)這也沒(méi)多少開銷,但是如果當(dāng)新的數(shù)據(jù)3造成這個(gè)頁(yè)A滿了,那么就要看它后面的頁(yè)B是否有空間,如果有空間,這時(shí)候頁(yè)B的開始數(shù)據(jù)應(yīng)該是這個(gè)從頁(yè)A溢出來(lái)的那條,對(duì)應(yīng)的也要移動(dòng)數(shù)據(jù)。

如果此時(shí)頁(yè)B也沒(méi)有足夠的空間,那么就要申請(qǐng)新的頁(yè)C,然后移一部分?jǐn)?shù)據(jù)到這個(gè)新頁(yè)C上,并且會(huì)切斷頁(yè)A與頁(yè)B之間的關(guān)系,在兩者之間插入一個(gè)頁(yè)C,從代碼的層面來(lái)說(shuō),就是切換鏈表的指針。

總結(jié)來(lái)說(shuō),不連續(xù)的身份證號(hào)當(dāng)主鍵可能會(huì)造成頁(yè)數(shù)據(jù)的移動(dòng)、隨機(jī)IO、頻繁申請(qǐng)新頁(yè)相關(guān)的開銷。如果我們用的是自增的主鍵,那么對(duì)于id來(lái)說(shuō)一定是順序的,不會(huì)因?yàn)殡S機(jī)IO造成數(shù)據(jù)移動(dòng)的問(wèn)題,在插入方面開銷一定是相對(duì)較小的。

其實(shí)不推薦用身份證號(hào)當(dāng)主鍵的還有另外一個(gè)原因:身份證號(hào)作為數(shù)字來(lái)說(shuō)太大了,得用bigint來(lái)存,正常來(lái)說(shuō)一個(gè)學(xué)校的學(xué)生用int已經(jīng)足夠了,我們知道一頁(yè)可以存放16K,當(dāng)一個(gè)索引本身占用的空間越大時(shí),會(huì)導(dǎo)致一頁(yè)能存放的數(shù)據(jù)越少,所以在一定數(shù)據(jù)量的情況下,使用bigint要比int需要更多的頁(yè)也就是更多的存儲(chǔ)空間。

3.聯(lián)合索引的矛與盾

由上面兩條結(jié)論可以得出:

  • 盡量不要去回表
  • 身份證號(hào)不適合當(dāng)主鍵索引

所以自然而然地想到了聯(lián)合索引,創(chuàng)建一個(gè)【身份證號(hào)+姓名】的聯(lián)合索引,注意聯(lián)合索引的順序,要符合最左原則。這樣當(dāng)我們同樣執(zhí)行以下sql時(shí):

select name from user where id_card=xxx

不需要回表就可以得到我們需要的name字段,然而還是沒(méi)有解決身份證號(hào)本身占用空間過(guò)大的問(wèn)題,這是業(yè)務(wù)數(shù)據(jù)本身的問(wèn)題,如果你要解決它的話,我們可以通過(guò)一些轉(zhuǎn)換算法將原本大的數(shù)據(jù)轉(zhuǎn)換成小的數(shù)據(jù),比如crc32:

crc32.ChecksumIEEE([]byte("341124199408203232"))

可以將原本需要8個(gè)字節(jié)存儲(chǔ)空間的身份證號(hào)用4個(gè)字節(jié)的crc碼替代,因此我們的數(shù)據(jù)庫(kù)需要再加個(gè)字段crc_id_card,聯(lián)合索引也從【身份證號(hào)+姓名】變成了【crc32(身份證號(hào))+姓名】,聯(lián)合索引占的空間變小了。但是這種轉(zhuǎn)換也是有代價(jià)的:

  • 每次額外的crc,導(dǎo)致需要更多cpu資源
  • 額外的字段,雖然讓索引的空間變小了,但是本身也要占用空間
  • crc會(huì)存在沖突的概率,這需要我們查詢出來(lái)數(shù)據(jù)后,再根據(jù)id_card過(guò)濾一下,過(guò)濾的成本根據(jù)重復(fù)數(shù)據(jù)的數(shù)量而定,重復(fù)越多,過(guò)濾越慢。

關(guān)于聯(lián)合索引存儲(chǔ)優(yōu)化,這里有個(gè)小細(xì)節(jié),假設(shè)現(xiàn)在有兩個(gè)字段A和B,分別占用8個(gè)字節(jié)和20個(gè)字節(jié),我們?cè)诼?lián)合索引已經(jīng)是[A,B]的情況下,還要支持B的單獨(dú)查詢,因此自然而然我們?cè)贐上也建立個(gè)索引,那么兩個(gè)索引占用的空間為?8+20+20=48,現(xiàn)在無(wú)論我們通過(guò)A還是通過(guò)B查詢都可以用到索引,如果在業(yè)務(wù)允許的條件下,我們是否可以建立[B,A]和A索引,這樣的話,不僅滿足單獨(dú)通過(guò)A或者B查詢數(shù)據(jù)用到索引,還可以占用更小的空間:20+8+8=36。

4.前綴索引的短小精悍

有時(shí)候我們需要索引的字段是字符串類型的,并且這個(gè)字符串很長(zhǎng),我們希望這個(gè)字段加上索引,但是我們又不希望這個(gè)索引占用太多的空間,這時(shí)可以考慮建立個(gè)前綴索引,以這個(gè)字段的前一部分字符建立個(gè)索引,這樣既可以享受索引,又可以節(jié)省空間,這里需要注意的是在前綴重復(fù)度較高的情況下,前綴索引和普通索引的速度應(yīng)該是有差距的。

alter table xx add index(name(7));#name前7個(gè)字符建立索引
select xx from xx where name="JamesBond"

5.唯一索引的快與慢

在說(shuō)唯一索引之前,我們先了解下普通索引的特點(diǎn),我們知道對(duì)于B+樹而言,葉子節(jié)點(diǎn)的數(shù)據(jù)是有序的。

假設(shè)現(xiàn)在我們要查詢2這條數(shù)據(jù),那么在通過(guò)索引樹找到2的時(shí)候,存儲(chǔ)引擎并沒(méi)有停止搜索,因?yàn)榭赡艽嬖诙鄠€(gè)2,這表現(xiàn)為存儲(chǔ)引擎會(huì)在葉子節(jié)點(diǎn)上接著向后查找,在找到第二個(gè)2之后,就停止了嗎?答案是否,因?yàn)榇鎯?chǔ)引擎并不知道后面還有沒(méi)有更多的2,所以得接著向后查找,直至找到第一個(gè)不是2的數(shù)據(jù),也就是3,找到3之后,停止檢索,這就是普通索引的檢索過(guò)程。

唯一索引就不一樣了,因?yàn)槲ㄒ恍?,不可能存在重?fù)的數(shù)據(jù),所以在檢索到我們的目標(biāo)數(shù)據(jù)之后直接返回,不會(huì)像普通索引那樣還要向后多查找一次,從這個(gè)角度來(lái)看,唯一索引是要比普通索引快的,但是當(dāng)普通索引的數(shù)據(jù)都在一個(gè)頁(yè)內(nèi)的話,其實(shí)也并不會(huì)快多少。在數(shù)據(jù)的插入方面,唯一索引可能就稍遜色,因?yàn)槲ㄒ恍裕看尾迦氲臅r(shí)候,都需要將判斷要插入的數(shù)據(jù)是否已經(jīng)存在,而普通索引不需要這個(gè)邏輯,并且很重要的一點(diǎn)是唯一索引會(huì)用不到change buffer(見下文)。

6.不要盲目加索引

在工作中,你可能會(huì)遇到這樣的情況:這個(gè)字段我需不需要加索引?。對(duì)于這個(gè)問(wèn)題,我們常用的判斷手段就是:查詢會(huì)不會(huì)用到這個(gè)字段,如果這個(gè)字段經(jīng)常在查詢的條件中,我們可能會(huì)考慮加個(gè)索引。但是如果只根據(jù)這個(gè)條件判斷,你可能會(huì)加了一個(gè)錯(cuò)誤的索引。我們來(lái)看個(gè)例子:假設(shè)有張用戶表,大概有100w的數(shù)據(jù),用戶表中有個(gè)性別字段表示男女,男女差不多各占一半,現(xiàn)在我們要統(tǒng)計(jì)所有男生的信息,然后我們給性別字段加了索引,并且我們這樣寫下了sql:

select * from user where sex="男"

如果不出意外的話,InnoDB是不會(huì)選擇性別這個(gè)索引的。如果走性別索引,那么一定是需要回表的,在數(shù)據(jù)量很大的情況下,回表會(huì)造成什么樣的后果?我貼一張和上面一樣的圖想必大家都知道了:

主要就是大量的IO,一條數(shù)據(jù)需要4次,那么50w的數(shù)據(jù)呢?結(jié)果可想而知。因此針對(duì)這種情況,MySQL的優(yōu)化器大概率走全表掃描,直接掃描主鍵索引,因?yàn)檫@樣性能可能會(huì)更高。

7.索引失效那些事

某些情況下,因?yàn)槲覀冏约菏褂玫牟划?dāng),導(dǎo)致mysql用不到索引,這一般很容易發(fā)生在類型轉(zhuǎn)換方面,也許你會(huì)說(shuō),mysql不是已經(jīng)支持隱式轉(zhuǎn)換了嗎?比如現(xiàn)在有個(gè)整型的user_id索引字段,我們因?yàn)椴樵兊臅r(shí)候沒(méi)注意,寫成了:

select xx from user where user_id="1234"

注意這里是字符的1234,當(dāng)發(fā)生這種情況下,MySQL確實(shí)足夠聰明,會(huì)把字符的1234轉(zhuǎn)成數(shù)字的1234,然后愉快的使用了user_id索引。 但是如果我們有個(gè)字符型的user_id索引字段,還是因?yàn)槲覀儾樵兊臅r(shí)候沒(méi)注意,寫成了:

select xx from user where user_id=1234

這時(shí)候就有問(wèn)題了,會(huì)用不到索引,也許你會(huì)問(wèn),這時(shí)MySQL為什么不會(huì)轉(zhuǎn)換了,把數(shù)字的1234轉(zhuǎn)成字符型的1234不就行了? 這里需要解釋下轉(zhuǎn)換的規(guī)則了,當(dāng)出現(xiàn)字符串和數(shù)字比較的時(shí)候,要記?。篗ySQL會(huì)把字符串轉(zhuǎn)換成數(shù)字。也許你又會(huì)問(wèn):為什么把字符型user_id字段轉(zhuǎn)換成數(shù)字就用不到索引了? 這又要說(shuō)到B+樹索引的結(jié)構(gòu)了,我們知道B+樹的索引是按照索引的值來(lái)分叉和排序的,當(dāng)我們把索引字段發(fā)生類型轉(zhuǎn)換時(shí)會(huì)發(fā)生值的變化,比如原來(lái)是A值,如果執(zhí)行整型轉(zhuǎn)換可能會(huì)對(duì)應(yīng)一個(gè)B值(int(A)=B),這時(shí)這顆索引樹就不能用了,因?yàn)樗饕龢涫前凑誂來(lái)構(gòu)造的,不是B,所以會(huì)用不到索引。

索引優(yōu)化

1.change buffer

我們知道在更新一條數(shù)據(jù)的時(shí)候,要先判斷這條數(shù)據(jù)的頁(yè)是否在內(nèi)存里,如果在的話,直接更新對(duì)應(yīng)的內(nèi)存頁(yè),如果不在的話,只能去磁盤把對(duì)應(yīng)的數(shù)據(jù)頁(yè)讀到內(nèi)存中來(lái),然后再更新,這會(huì)有什么問(wèn)題呢?

  • 去磁盤的讀這個(gè)動(dòng)作稍顯的有點(diǎn)慢
  • 如果同時(shí)更新很多數(shù)據(jù),那么即有可能發(fā)生很多離散的IO

為了解決這種情況下的速度問(wèn)題,change buffer出現(xiàn)了,首先不要被buffer這個(gè)單詞誤導(dǎo),change buffer除了會(huì)在公共的buffer pool里之外,也是會(huì)持久化到磁盤的。當(dāng)有了change buffer之后,我們更新的過(guò)程中,如果發(fā)現(xiàn)對(duì)應(yīng)的數(shù)據(jù)頁(yè)不在內(nèi)存里的話,也不去磁盤讀取相應(yīng)的數(shù)據(jù)頁(yè)了,而是把要更新的數(shù)據(jù)放入到change buffer中,那change buffer的數(shù)據(jù)何時(shí)被同步到磁盤上去?如果此時(shí)發(fā)生讀動(dòng)作怎么辦?首先后臺(tái)有個(gè)線程會(huì)定期把change buffer的數(shù)據(jù)同步到磁盤上去的,如果線程還沒(méi)來(lái)得及同步,但是又發(fā)生了讀操作,那么也會(huì)觸發(fā)把change buffer的數(shù)據(jù)merge到磁盤的事件。

需要注意的是并不是所有的索引都能用到changer buffer,像主鍵索引和唯一索引就用不到,因?yàn)槲ㄒ恍裕运鼈冊(cè)诟碌臅r(shí)候要判斷數(shù)據(jù)存不存在,如果數(shù)據(jù)頁(yè)不在內(nèi)存中,就必須去磁盤上把對(duì)應(yīng)的數(shù)據(jù)頁(yè)讀到內(nèi)存里,而普通索引就沒(méi)關(guān)系了,不需要校驗(yàn)唯一性。change buffer越大,理論收益就越大,這是因?yàn)槭紫入x散的讀IO變少了,其次當(dāng)一個(gè)數(shù)據(jù)頁(yè)上發(fā)生多次變更,只需merge一次到磁盤上。當(dāng)然并不是所有的場(chǎng)景都適合changer buffer,如果你的業(yè)務(wù)是更新之后,需要立馬去讀,changer buffer會(huì)適得其反,因?yàn)樾枰煌5赜|發(fā)merge動(dòng)作,導(dǎo)致隨機(jī)IO的次數(shù)不會(huì)變少,反而增加了維護(hù)changer buffer的開銷。

2.索引下推

前面我們說(shuō)了聯(lián)合索引,聯(lián)合索引要滿足最左原則,即在聯(lián)合索引是[A,B]的情況下,我們可以通過(guò)以下的sql用到索引:

select * from table where A="xx"
select * from table where A="xx" AND B="xx"

其實(shí)聯(lián)合索引也可以使用最左前綴的原則,即:

select * from table where A like "趙%" AND B="上海市"

但是這里需要注意的是,因?yàn)槭褂昧薃的一部分,在MySQL5.6之前,上面的sql在檢索出所有A是“趙”開頭的數(shù)據(jù)之后,就立馬回表(使用的select *),然后再對(duì)比B是不是“上海市”這個(gè)判斷,這里是不是有點(diǎn)懵?為什么B這個(gè)判斷不直接在聯(lián)合索引上判斷,這樣的話回表的次數(shù)不就少了嗎?造成這個(gè)問(wèn)題的原因還是因?yàn)槭褂昧俗钭笄熬Y的問(wèn)題,導(dǎo)致索引雖然能使用部分A,但是完全用不到B,看起來(lái)是有點(diǎn)“傻”,于是在MySQL5.6之后,就出現(xiàn)了索引下推這個(gè)優(yōu)化(Index Condition Pushdown),有了這個(gè)功能以后,雖然使用的是最左前綴,但是也可以在聯(lián)合索引上搜索出符合A%的同時(shí)也過(guò)濾非B的數(shù)據(jù),大大減少了回表的次數(shù)。

3.刷新鄰接頁(yè)

在說(shuō)刷新鄰接頁(yè)之前,我們先說(shuō)下臟頁(yè),我們知道在更新一條數(shù)據(jù)的時(shí)候,得先判斷這條數(shù)據(jù)所在的頁(yè)是否在內(nèi)存中,如果不在的話,需要把這個(gè)數(shù)據(jù)頁(yè)先讀到內(nèi)存中,然后再更新內(nèi)存中的數(shù)據(jù),這時(shí)會(huì)發(fā)現(xiàn)內(nèi)存中的頁(yè)有最新的數(shù)據(jù),但是磁盤上的頁(yè)卻依然是老數(shù)據(jù),那么此時(shí)這條數(shù)據(jù)所在的內(nèi)存中的頁(yè)就是臟頁(yè),需要刷到磁盤上來(lái)保持一致。所以問(wèn)題來(lái)了,何時(shí)刷?每次刷多少臟頁(yè)才合適?如果每次變更就刷,那么性能會(huì)很差,如果很久才刷,臟頁(yè)就會(huì)堆積很多,造成內(nèi)存池中可用的頁(yè)變少,進(jìn)而影響正常的功能。所以刷的速度不能太快但要及時(shí),MySQL有個(gè)清理線程會(huì)定期執(zhí)行,保證了不會(huì)太快,當(dāng)臟頁(yè)太多或者redo log已經(jīng)快滿了,也會(huì)立刻觸發(fā)刷盤,保證了及時(shí)。

在臟頁(yè)刷盤的過(guò)程中,InnoDB這里有個(gè)優(yōu)化:如果要刷的臟頁(yè)的鄰居頁(yè)也臟了,那么就順帶一起刷,這樣的好處就是可以減少隨機(jī)IO,在機(jī)械磁盤的情況下,優(yōu)化應(yīng)該挺大,但是這里可能會(huì)有坑,如果當(dāng)前臟頁(yè)的鄰居臟頁(yè)在被一起刷入后,鄰居頁(yè)立馬因?yàn)閿?shù)據(jù)的變更又變臟了,那此時(shí)是不是有種多此一舉的感覺,并且反而浪費(fèi)了時(shí)間和開銷。更糟糕的是如果鄰居頁(yè)的鄰居也是臟頁(yè)...,那么這個(gè)連鎖反應(yīng)可能會(huì)出現(xiàn)短暫的性能問(wèn)題。

4.MRR

在實(shí)際業(yè)務(wù)中,我們可能會(huì)被告知盡量使用覆蓋索引,不要回表,因?yàn)榛乇硇枰郔O,耗時(shí)更長(zhǎng),但是有時(shí)候我們又不得不回表,回表不僅僅會(huì)造成過(guò)多的IO,更嚴(yán)重的是過(guò)多的離散IO。

select * from user where grade between 60 and 70

現(xiàn)在要查詢成績(jī)?cè)?0-70之間的用戶信息,于是我們的sql寫成上面的那樣,當(dāng)然我們的grade字段是有索引的,按照常理來(lái)說(shuō),會(huì)先在grade索引上找到grade=60這條數(shù)據(jù),然后再根據(jù)grade=60這條數(shù)據(jù)對(duì)應(yīng)的id去主鍵索引上找,最后再次回到grade索引上,不停的重復(fù)同樣的動(dòng)作..., 假設(shè)現(xiàn)在grade=60對(duì)應(yīng)的id=1,數(shù)據(jù)是在page_no_1上,grade=61對(duì)應(yīng)的id=10,數(shù)據(jù)是在page_no_2上,grade=62對(duì)應(yīng)的id=2,數(shù)據(jù)是在page_no_1上,所以真實(shí)的情況就是先在page_no_1上找數(shù)據(jù),然后切到page_no_2,最后又切回page_no_1上,但其實(shí)id=1id=2完全可以合并,讀一次page_no_1即可,不僅節(jié)省了IO,同時(shí)避免了隨機(jī)IO,這就是MRR。當(dāng)使用MRR之后,輔助索引不會(huì)立即去回表,而是將得到的主鍵id,放在一個(gè)buffer中,然后再對(duì)其排序,排序后再去順序讀主鍵索引,大大減少了離散的IO。

最后

以上就是MySQL數(shù)據(jù)庫(kù)索引的坑及合理利用的詳細(xì)內(nèi)容,更多關(guān)于MySQL索引坑及合理利用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Mysql?數(shù)據(jù)庫(kù)結(jié)構(gòu)及索引類型

    Mysql?數(shù)據(jù)庫(kù)結(jié)構(gòu)及索引類型

    這篇文章主要介紹了Mysql?數(shù)據(jù)庫(kù)結(jié)構(gòu)及索引類型,數(shù)據(jù)庫(kù)索引是?mysql?數(shù)據(jù)庫(kù)中重要的組成部分,是數(shù)據(jù)庫(kù)查詢數(shù)據(jù)速度提升的關(guān)鍵,本文將介紹數(shù)據(jù)庫(kù)索引的一些內(nèi)容,下文更多相關(guān)內(nèi)容,需要的小伙伴可以參考一下
    2022-05-05
  • mysql實(shí)現(xiàn)根據(jù)多個(gè)字段查找和置頂功能

    mysql實(shí)現(xiàn)根據(jù)多個(gè)字段查找和置頂功能

    在mysql中,如果要實(shí)現(xiàn)根據(jù)某個(gè)字段排序的時(shí)候,可以使用下面的SQL語(yǔ)句,下面為大家介紹下如何實(shí)現(xiàn)根據(jù)多個(gè)字段查找和置頂功能
    2013-11-11
  • 詳解MySQL數(shù)據(jù)備份之mysqldump使用方法

    詳解MySQL數(shù)據(jù)備份之mysqldump使用方法

    本篇文章主要介紹了MySQL數(shù)據(jù)備份,詳細(xì)的介紹了mysqldump的各種用法,具有一定的參考價(jià)值,有需要的可以了解一下。
    2016-11-11
  • 實(shí)例講解MySQL中樂(lè)觀鎖和悲觀鎖

    實(shí)例講解MySQL中樂(lè)觀鎖和悲觀鎖

    在本篇文章里我們通過(guò)實(shí)例總結(jié)了關(guān)于MySQL中樂(lè)觀鎖和悲觀鎖區(qū)別的知識(shí)點(diǎn),有興趣的讀者們學(xué)習(xí)下。
    2019-02-02
  • mysql 主從復(fù)制如何跳過(guò)報(bào)錯(cuò)

    mysql 主從復(fù)制如何跳過(guò)報(bào)錯(cuò)

    這篇文章主要介紹了mysql 主從復(fù)制如何跳過(guò)報(bào)錯(cuò),幫助大家更好的理解和使用MySQL 數(shù)據(jù)庫(kù),感興趣的朋友可以了解下
    2020-10-10
  • 關(guān)于sql?count(列名)、count(常量)、count(*)之間的區(qū)別

    關(guān)于sql?count(列名)、count(常量)、count(*)之間的區(qū)別

    這篇文章主要介紹了關(guān)于sql?count(列名)、count(常量)、count(*)之間的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 為什么mysql字段要使用NOT NULL

    為什么mysql字段要使用NOT NULL

    數(shù)據(jù)庫(kù)字段一定要設(shè)置為 not null,不然會(huì)有很大的bug,下面就一起來(lái)介紹一下,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • MySql分表、分庫(kù)、分片和分區(qū)知識(shí)點(diǎn)介紹

    MySql分表、分庫(kù)、分片和分區(qū)知識(shí)點(diǎn)介紹

    數(shù)據(jù)庫(kù)的數(shù)據(jù)量達(dá)到一定程度之后,為避免帶來(lái)系統(tǒng)性能上的瓶頸。需要進(jìn)行數(shù)據(jù)的處理,采用的手段是分區(qū)、分片、分庫(kù)、分表,這里就為大家介紹一下,需要的朋友可以參考下
    2020-02-02
  • MySQL一鍵安裝Shell腳本的實(shí)現(xiàn)

    MySQL一鍵安裝Shell腳本的實(shí)現(xiàn)

    本文主要介紹了MySQL一鍵安裝Shell腳本,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • mysqld-nt: Out of memory (Needed 1677720 bytes)解決方法

    mysqld-nt: Out of memory (Needed 1677720 bytes)解決方法

    這篇文章主要介紹了mysqld-nt: Out of memory (Needed 1677720 bytes)解決方法,需要的朋友可以參考下
    2014-12-12

最新評(píng)論

基隆市| 包头市| 施秉县| 呼伦贝尔市| 克东县| 拜城县| 新宾| 宽甸| 舟曲县| 马尔康县| 宝清县| 疏附县| 富蕴县| 长宁区| 城步| 通许县| 新丰县| 江永县| 周宁县| 逊克县| 江阴市| 信宜市| 彝良县| 双峰县| 德兴市| 鄱阳县| 合水县| 临猗县| 莫力| 黑河市| 炉霍县| 光山县| 天峨县| 宣化县| 潼南县| 汤阴县| 莎车县| 如皋市| 沽源县| 基隆市| 深泽县|