mysql索引淺析

MySQL 的索引長什么樣子狞膘?索引到底是怎么加速查詢的研乒?

事實(shí)上,在你還沒有執(zhí)行?create index?語句的時候佳窑,MySQL 就已經(jīng)創(chuàng)建索引了制恍。

聚簇索引

執(zhí)行建表語句:

CREATE TABLE `student` (

`id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL COMMENT '主鍵id',

`student_no` VARCHAR ( 64 ) COMMENT '學(xué)號',

`name` VARCHAR ( 64 ) COMMENT '學(xué)生姓名',

`age` INT COMMENT '學(xué)生年齡',

PRIMARY KEY ( `id` )) ENGINE = INNODB CHARSET = utf8mb4 COMMENT = '學(xué)生信息表';

插入 5 條數(shù)據(jù):

INSERT INTO student ( student_no, NAME, age )

VALUES

( 101, "Alice", 18 ),

( 102, "Bob", 19 ),

( 104, "Brandt", 15 ),

( 105, "David", 19 ),

( 109, "David", 18 );

在插入的過程中,MySQL 會用你指定的主鍵神凑,在這里是遞增主鍵净神,維護(hù)起一棵 B+樹,主鍵從 1 開始遞增耙厚,插入五條强挫,所以是 1 到 5:


索引樹

從 1 到 5,一個一個插入薛躬,你會看到 B+樹在插入的過程中是怎么維護(hù)它的幾個特性的:

有序:左邊節(jié)點(diǎn)比右邊小

自平衡:左右兩邊數(shù)量趨于相等

節(jié)點(diǎn)分裂:節(jié)點(diǎn)在遇到元素數(shù)量超過節(jié)點(diǎn)容量時俯渤,是如何分裂成兩個的,這個也是 MySQL 頁分裂的原理

模擬工具只支持插入一個值型宝,所以你看不到主鍵之外的其他數(shù)據(jù)八匠,實(shí)際上,這棵 B+樹的葉子節(jié)點(diǎn)是帶有行的全部數(shù)據(jù)的:


完整樹結(jié)構(gòu)

如果沒有這棵 B+樹趴酣,你要根據(jù)主鍵查詢梨树,比如

select*fromstudentwhereid=5;

數(shù)據(jù)是無序的,你只能全表掃描

有同學(xué)會說主鍵不是遞增的嗎岖寞,那不就可以用二分法來查找抡四?不是的,主鍵雖然是遞增的仗谆,但是如果你寫入磁盤時指巡,沒有去維護(hù)有序數(shù)組這樣一個數(shù)據(jù)結(jié)構(gòu)(比如你刪掉了 4,怎么把 5 往前面挪)隶垮,那數(shù)據(jù)在磁盤里依舊是無序的藻雪,查找時只能隨機(jī)查找,而如果你維護(hù)了有序數(shù)組這樣的數(shù)據(jù)結(jié)構(gòu)狸吞,其實(shí)也是建了索引勉耀,只是建了不一樣的數(shù)據(jù)結(jié)構(gòu)的索引罷了。

現(xiàn)在有了這棵 B+樹蹋偏,數(shù)據(jù)被有規(guī)律的存儲起來便斥,查找id=5,也不再大浪淘沙威始,而是變得很有章法:

從上到下椭住,先找到 3,5 比它大字逗,找右節(jié)點(diǎn)

接著找到 4京郑,發(fā)現(xiàn) 5 還是比它大宅广,繼續(xù)找右節(jié)點(diǎn)

這次到達(dá)葉子節(jié)點(diǎn)了,葉子節(jié)點(diǎn)是一個遞增的數(shù)組些举,那就用二分法跟狱,找到?id=5?的數(shù)據(jù)

你要訪問磁盤的次數(shù),是由這棵樹的層數(shù)決定的户魏。為了方便說明驶臊,我在文章里舉的例子的數(shù)據(jù)量不會太大,所以用不用索引叼丑,性能提升的效果不明顯关翎,但是你可以腦補(bǔ)下大數(shù)據(jù)量的畫面。

如果你沒有指定主鍵呢鸠信?沒關(guān)系纵寝,唯一鍵也可以。

連唯一鍵也沒有星立?也沒關(guān)系爽茴,mysql會給你建一個rowid字段,用它來組織這棵 B+樹.

反正 MySQL 就一個目的绰垂,數(shù)據(jù)要有規(guī)律的存儲起來室奏,數(shù)據(jù)是否被規(guī)律的管理起來,是數(shù)據(jù)庫和文件系統(tǒng)區(qū)分開來的重要因素劲装。

這個 MySQL 無論如何都會建起來胧沫,并且存儲有完整行數(shù)據(jù)的索引,就叫聚簇索引(clustered index)占业。

二級索引

聚簇索引只能幫你加快主鍵查詢绒怨,但是如果你想根據(jù)姓名查詢呢?

對不起纺酸,看看上面這棵樹你就知道窖逗,數(shù)據(jù)并沒有按照姓名進(jìn)行組織址否,所以餐蔬,你還是只能全表掃描。

不想全表掃描佑附,怎么辦樊诺?那就給姓名字段也加個索引,讓數(shù)據(jù)按照姓名有規(guī)律的進(jìn)行組織:

create index idx_name onstudent(name);

這時候 MySQL 又會建一棵新的 B+樹:


name索引樹


你會發(fā)現(xiàn)這棵樹的葉子節(jié)點(diǎn)音同,只有姓名和主鍵ID兩個字段词爬,沒有行的完整數(shù)據(jù),這時候你執(zhí)行:

select*fromstudentwherename="David";

MySQL 到你剛剛創(chuàng)建的這棵 B+樹 查詢权均,快速查到有兩條姓名是“David”的記錄顿膨,并且拿到它們的主鍵锅锨,分別是 4 和 5,但是你要的是select *呀恋沃,怎么辦必搞?

別忘了,MySQL 在一開始就給你建了一棵 B+樹 了囊咏,把這兩棵樹恕洲,放在一起,拿著從這棵樹上查到的兩個主鍵ID梅割,去聚簇索引找霜第,事情不就解決了?


查找過程

這個不帶行數(shù)據(jù)完整信息的索引户辞,就叫二級索引(secondary index)泌类,也叫輔助索引。

復(fù)合索引

繼續(xù)咆课,如果我還想根據(jù)姓名和年齡同時查詢呢末誓?

select*fromstudentwherename="David"and age=18;

還是那個道理,數(shù)據(jù)雖然按照 name 有規(guī)律的組織了书蚪,但是沒有按照 age 有規(guī)律組織喇澡,所以我們要給name和age同時建索引:

create index idx_name_age onstudent(name,age);

這時候 MySQL 又會建一棵 B+樹,這下 B+樹 的節(jié)點(diǎn)里面殊校,不只有 name晴玖,還有 age 了:


查詢過程

注意觀察我用紅色虛線框出來的那兩個節(jié)點(diǎn),這是這棵樹和上面那棵只給 name 建索引的樹的唯一區(qū)別为流,兩個元素?fù)Q了個位呕屎,因?yàn)榕判驎r,是先用 name 比較大小敬察,如果 name 相同秀睛,則用 age 比較

還是那句話莲祸,這里舉的例子數(shù)據(jù)量很少蹂安,你可以想象下有一萬個叫“David”的學(xué)生,年齡隨機(jī)分布在 13 到 20 之間锐帜,這時候如果沒有按照 age 進(jìn)行有規(guī)律的存儲田盈,你還是得掃描一萬行數(shù)據(jù)。

只給 student 表建idx_name_age這個復(fù)合索引缴阎,這兩個 sql 語句允瞧,會走索引嗎?

select*fromstudentwherename="David";

select*fromstudentwhereage=18;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市述暂,隨后出現(xiàn)的幾起案子痹升,更是在濱河造成了極大的恐慌,老刑警劉巖畦韭,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件视卢,死亡現(xiàn)場離奇詭異,居然都是意外死亡廊驼,警方通過查閱死者的電腦和手機(jī)据过,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妒挎,“玉大人绳锅,你說我怎么就攤上這事≡脱冢” “怎么了鳞芙?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長期虾。 經(jīng)常有香客問我原朝,道長,這世上最難降的妖魔是什么镶苞? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任喳坠,我火速辦了婚禮,結(jié)果婚禮上茂蚓,老公的妹妹穿的比我還像新娘壕鹉。我一直安慰自己,他們只是感情好聋涨,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布晾浴。 她就那樣靜靜地躺著,像睡著了一般牍白。 火紅的嫁衣襯著肌膚如雪脊凰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天茂腥,我揣著相機(jī)與錄音狸涌,去河邊找鬼。 笑死础芍,一個胖子當(dāng)著我的面吹牛杈抢,可吹牛的內(nèi)容都是我干的数尿。 我是一名探鬼主播仑性,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼右蹦!你這毒婦竟也來了诊杆?” 一聲冷哼從身側(cè)響起歼捐,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晨汹,沒想到半個月后豹储,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡淘这,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年剥扣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铝穷。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡钠怯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出曙聂,到底是詐尸還是另有隱情晦炊,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布宁脊,位于F島的核電站断国,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏榆苞。R本人自食惡果不足惜稳衬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坐漏。 院中可真熱鬧宋彼,春花似錦、人聲如沸仙畦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慨畸。三九已至莱坎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寸士,已是汗流浹背檐什。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弱卡,地道東北人乃正。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像婶博,于是被迫代替她去往敵國和親瓮具。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348