掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
金三銀四很快就要來啦,準(zhǔn)備了索引的15連問,相信大家看完肯定會有幫助的。

10年積累的成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認識你,你也不認識我。但先網(wǎng)站設(shè)計后付款的網(wǎng)站建設(shè)流程,更有新邵免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
可以從幾個維度去看這個問題,查詢是否夠快,效率是否穩(wěn)定,存儲數(shù)據(jù)多少, 以及查找磁盤次數(shù),為什么不是二叉樹,為什么不是平衡二叉樹,為什么不是 B 樹,而偏偏是 B+樹呢?
如果二叉樹特殊化為一個鏈表,相當(dāng)于全表掃描。平衡二叉樹相比于二叉查找 樹來說,查找效率更穩(wěn)定,總體的查找速度也更快。
我們知道,在內(nèi)存比在磁盤的數(shù)據(jù),查詢效率快得多。如果樹這種數(shù)據(jù)結(jié)構(gòu)作 為索引,那我們每查找一次數(shù)據(jù)就需要從磁盤中讀取一個節(jié)點,也就是我們說 的一個磁盤塊,但是平衡二叉樹可是每個節(jié)點只存儲一個鍵值和數(shù)據(jù)的,如果 是 B 樹,可以存儲更多的節(jié)點數(shù)據(jù),樹的高度也會降低,因此讀取磁盤的次數(shù) 就降下來啦,查詢效率就快啦。
假設(shè)有以下表結(jié)構(gòu),并且初始化了這幾條數(shù)據(jù)
CREATE TABLE `employee` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`date` datetime DEFAULT NULL,
`sex` int(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_age` (`age`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into employee values(100,'小倫',43,'2021-01-20','0');
insert into employee values(200,'俊杰',48,'2021-01-21','0');
insert into employee values(300,'紫琪',36,'2020-01-21','1');
insert into employee values(400,'立紅',32,'2020-01-21','0');
insert into employee values(500,'易迅',37,'2020-01-21','1');
insert into employee values(600,'小軍',49,'2021-01-21','0');
insert into employee values(700,'小燕',28,'2021-01-21','1');執(zhí)行這條查詢SQL,需要執(zhí)行幾次的樹搜索操作?可以畫下對應(yīng)的索引樹結(jié)構(gòu)圖~
select * from Temployee where age=32;其實這個,這個大家可以先畫出idx_age普通索引的索引結(jié)構(gòu)圖,大概如下:
再畫出id主鍵索引,我們先畫出聚族索引結(jié)構(gòu)圖,如下:
這條 SQL 查詢語句執(zhí)行大概流程是這樣的:
當(dāng)查詢的數(shù)據(jù)在索引樹中,找不到的時候,需要回到主鍵索引樹中去獲取,這個過程叫做回表。
比如在第6小節(jié)中,使用的查詢SQL
select * from employee where age=32;需要查詢所有列的數(shù)據(jù),idx_age普通索引不能滿足,需要拿到主鍵id的值后,再回到id主鍵索引查找獲取,這個過程就是回表。
如果我們查詢SQL的select * 修改為 select id, age的話,其實是不需要回表的。因為id和age的值,都在idx_age索引樹的葉子節(jié)點上,這就涉及到覆蓋索引的只是點了。
覆蓋索引是select的數(shù)據(jù)列只用從索引中就能夠取得,不必回表,換句話說,查詢列要被所建的索引覆蓋。
索引的最左前綴原則,可以是聯(lián)合索引的最左N個字段。比如你建立一個組合索引(a,b,c),其實可以相當(dāng)于建了(a),(a,b),(a,b,c)三個索引,大大提高了索引復(fù)用能力。
當(dāng)然,最左前綴也可以是字符串索引的最左M個字符。。 比如,你的普通索引樹是醬紫:
這個SQL: select * from employee where name like '小%' order by age desc; 也是命中索引的。
給你這個SQL:
select * from employee where name like '小%' and age=28 and sex='0';其中,name和age為聯(lián)合索引(idx_name_age)。
如果是Mysql5.6之前,在idx_name_age索引樹,找出所有名字第一個字是“小”的人,拿到它們的主鍵id,然后回表找出數(shù)據(jù)行,再去對比年齡和性別等其他字段。如圖:
有些朋友可能覺得奇怪,idx_name_age(name,age)不是聯(lián)合索引嘛?為什么選出包含“小”字后,不再順便看下年齡age再回表呢,不是更高效嘛?所以呀,MySQL 5.6就引入了索引下推優(yōu)化,可以在索引遍歷過程中,對索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數(shù)。
因此,MySQL5.6版本之后,選出包含“小”字后,順表過濾age=28
如果一張表數(shù)據(jù)量級是千萬級別以上的,那么,如何給這張表添加索引?
我們需要知道一點,給表添加索引的時候,是會對表加鎖的。如果不謹(jǐn)慎操作,有可能出現(xiàn)生產(chǎn)事故的??梢詤⒖家韵路椒ǎ?/p>
explain查看SQL的執(zhí)行計劃,這樣就知道是否命中索引了。
當(dāng)explain與SQL一起使用時,MySQL將顯示來自優(yōu)化器的有關(guān)語句執(zhí)行計劃的信息。
一般來說,我們需要重點關(guān)注type、rows、filtered、extra、key。
type表示連接類型,查看索引執(zhí)行情況的一個重要指標(biāo)。以下性能從好到壞依次:system > const > eq_ref > ref > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
該列表示MySQL估算要找到我們所需的記錄,需要讀取的行數(shù)。對于InnoDB表,此數(shù)字是估計值,并非一定是個準(zhǔn)確值。
該列是一個百分比的值,表里符合條件的記錄數(shù)的百分比。簡單點說,這個字段表示存儲引擎返回的數(shù)據(jù)在經(jīng)過過濾后,剩下滿足條件的記錄數(shù)量的比例。
該字段包含有關(guān)MySQL如何解析查詢的其他信息,它一般會出現(xiàn)這幾個值:
該列表示實際用到的索引。一般配合possible_keys列一起看。
優(yōu)點:
缺點:
聚簇索引并不是一種單獨的索引類型,而是一種數(shù)據(jù)存儲方式。它表示索引結(jié)構(gòu)和數(shù)據(jù)一起存放的索引。非聚集索引是索引結(jié)構(gòu)和數(shù)據(jù)分開存放的索引。
接下來,我們分不同存存儲引擎去聊哈~
在MySQL的InnoDB存儲引擎中, 聚簇索引與非聚簇索引最大的區(qū)別,在于葉節(jié)點是否存放一整行記錄。聚簇索引葉子節(jié)點存儲了一整行記錄,而非聚簇索引葉子節(jié)點存儲的是主鍵信息,因此,一般非聚簇索引還需要回表查詢。
而在MyISM存儲引擎中,它的主鍵索引,普通索引都是非聚簇索引,因為數(shù)據(jù)和索引是分開的,葉子節(jié)點都使用一個地址指向真正的表數(shù)據(jù)。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流