一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Mysql索引是什么東西?索引有哪些特性?索引是如何工作的?

OSC開(kāi)源社區(qū) ? 來(lái)源:OSCHINA 社區(qū) ? 2023-12-24 16:20 ? 次閱讀

1 索引如何工作,是如何加快查詢速度

索引就好比書(shū)本的目錄,提高數(shù)據(jù)庫(kù)表數(shù)據(jù)訪問(wèn)速度的數(shù)據(jù)庫(kù)對(duì)象。當(dāng)我們的請(qǐng)求打過(guò)來(lái)之后,如果有目錄,就會(huì)快速的定位到章節(jié),再?gòu)恼鹿?jié)里找到數(shù)據(jù)。如果沒(méi)有目錄,如大海撈針一般,難度可見(jiàn)一斑。這就是我們經(jīng)常碰到的罪魁禍?zhǔn)?,全表掃描?/p>

一條索引記錄中包含的基本信息包括:鍵值(即你定義索引時(shí)指定的所有字段的值)+ 邏輯指針(指向數(shù)據(jù)頁(yè)或者另一索引頁(yè))。通常狀況下,由于索引記錄僅包含索引字段值(以及 4-9 字節(jié)的指針),索引實(shí)體比真實(shí)的數(shù)據(jù)行要小許多,索引頁(yè)相較數(shù)據(jù)頁(yè)來(lái)說(shuō)要密集許多。一個(gè)索引頁(yè)可以存儲(chǔ)數(shù)量更多的索引記錄,這意味著在索引中查找時(shí)在 I/O 上占很大的優(yōu)勢(shì),理解這一點(diǎn)有助于從本質(zhì)上了解使用索引的優(yōu)勢(shì),也是大部分性能優(yōu)化所需要切入的點(diǎn)。

1)沒(méi)有索引的情況下訪問(wèn)數(shù)據(jù):

wKgZomWH6eqAFMrfAADx8vshyf0063.jpg

2)使用平衡二叉樹(shù)結(jié)構(gòu)索引的情況下訪問(wèn)數(shù)據(jù):

wKgZomWH6eqAT60_AAEg6oCFumo827.jpg

第一張圖沒(méi)有使用索引我們會(huì)進(jìn)行順序查找,依照數(shù)據(jù)順序逐個(gè)進(jìn)行匹配,進(jìn)行了 5 次尋址才查詢出所需數(shù)據(jù),第二張圖用了一個(gè)簡(jiǎn)單的平衡二叉樹(shù)索引之后我們只用了 3 次,這還是數(shù)據(jù)量小的情況下,數(shù)據(jù)量大了效果更明顯,所以總結(jié)來(lái)說(shuō)創(chuàng)建索引就是為了加快數(shù)據(jù)查找速度;

2 索引的組成部分和種類(lèi)

常見(jiàn)的索引的實(shí)現(xiàn)方式有很多種,比如 hash、數(shù)組、樹(shù),下面為大家介紹下這幾種模型使用上有什么區(qū)別

2.1 hash

hash 思路簡(jiǎn)單,就是把我們插入的 key 通過(guò) hash 函數(shù)算法 (以前一般是取余數(shù),就好比 hashmap 的計(jì)算方式移位異或之類(lèi)的),計(jì)算出對(duì)應(yīng)的 value,把這個(gè) value 放到一個(gè)位置,這個(gè)位置叫做哈希槽。對(duì)應(yīng)磁盤(pán)位置指針?lè)湃?hash 槽里面。一句話總結(jié) hash 索引,就是存儲(chǔ)了索引字段的 hash 值和數(shù)據(jù)所在磁盤(pán)文件指針。

但是不可避免的是,無(wú)論什么算法,數(shù)據(jù)量大了之后難免會(huì)出現(xiàn)不同的數(shù)據(jù)被放在一個(gè) hash 槽里面。比如字典上的 “吳” 和” 武” 就是同音,你查字典的時(shí)候到這里只能順序往下去找了。索引的處理也是這樣,會(huì)拉出一個(gè)鏈表,需要的時(shí)候順序遍歷即可。

wKgaomWH6eqAFNUhAAAxjbTNikM877.jpg

缺點(diǎn):無(wú)序索引,區(qū)間查詢性能低,因?yàn)閰^(qū)間查詢會(huì)造成多次訪問(wèn)磁盤(pán),多次 io 耗時(shí)是很難接受的。

優(yōu)點(diǎn):insert 迅速,只需往后補(bǔ)就行

場(chǎng)景:等值查詢, 比如 memcached 。不適用大量重復(fù)數(shù)據(jù)的列,避免 hash 沖突

總結(jié):想成 java 的 hashmap 即可

2.2 有序數(shù)組

如果我們需要區(qū)間查詢的時(shí)候,hash 索引的性能就不盡如人意了。這個(gè)時(shí)候有序數(shù)組的優(yōu)勢(shì)就能體現(xiàn)出來(lái)了。

當(dāng)我們需要從一個(gè)有序數(shù)組里取 A 和 B 之間的值時(shí),只需要通過(guò)二分法定位到 A 的位置,時(shí)間復(fù)雜度 O (log (N)), 接著從 A 遍歷到 B 即可,論速度的話,基本上可以說(shuō)是最快的了。但是當(dāng)我們需要更新的時(shí)候,需要進(jìn)行的操作就很多了。如果需要插入一條數(shù)據(jù),你需要挪動(dòng)數(shù)據(jù)之后的所有數(shù)據(jù),浪費(fèi)性能。所以總結(jié)來(lái)說(shuō),只有不怎么變化的數(shù)據(jù)適合有序數(shù)組結(jié)構(gòu)的索引。

缺點(diǎn):insert 新數(shù)據(jù)的時(shí)候,需要改變后續(xù)所有數(shù)據(jù),成本略高。

優(yōu)點(diǎn):查詢速度很快,理論最大值。

場(chǎng)景:歸檔查詢,日志查詢等極少變化的

總結(jié):就是順序排的數(shù)組

2.3 二叉搜索樹(shù)

基本原則是樹(shù)的左節(jié)點(diǎn)都小于父節(jié)點(diǎn),右節(jié)點(diǎn)都大于父節(jié)點(diǎn)

wKgaomWH6eqAaPHtAABl52c7HBY112.jpg

這里我們就能看出來(lái),二叉搜索樹(shù)的查詢效率原則上是 O (log (N)),為了保證是平衡二叉樹(shù),更新效率也是 O (log (N))。但是數(shù)據(jù)很多的情況樹(shù)的高度會(huì)達(dá)到很高,過(guò)多次訪問(wèn)磁盤(pán),是不可取的。并且極端情況下,樹(shù)退化成鏈表,查詢的復(fù)雜度會(huì)被拉成 O (n)。

進(jìn)化成多叉樹(shù),也就是多個(gè)子節(jié)點(diǎn)的時(shí)候,會(huì)大大的減少樹(shù)的高度,降低訪問(wèn)磁盤(pán)。

缺點(diǎn):數(shù)據(jù)量大的時(shí)候,樹(shù)會(huì)過(guò)高,導(dǎo)致多次訪問(wèn)磁盤(pán)

優(yōu)點(diǎn):進(jìn)化成多叉樹(shù),會(huì)降低樹(shù)高,訪問(wèn)磁盤(pán)次數(shù)。

場(chǎng)景:適用很多場(chǎng)景

總結(jié):左小右大的樹(shù)

2.4 B 樹(shù)

在每個(gè)節(jié)點(diǎn)存儲(chǔ)多個(gè)元素,在每個(gè)節(jié)點(diǎn)盡可能多的存儲(chǔ)數(shù)據(jù)。每個(gè)節(jié)點(diǎn)可以存儲(chǔ) 1000 個(gè)索引(16k/16=1000),這樣就將二叉樹(shù)改造成了多叉樹(shù),通過(guò)增加樹(shù)的叉樹(shù),將樹(shù)從高瘦變?yōu)榘?。?gòu)建 1 百萬(wàn)條數(shù)據(jù),樹(shù)的高度只需要 2 層就可以(1000*1000=1 百萬(wàn)),也就是說(shuō)只需要 2 次磁盤(pán) IO 就可以查詢到數(shù)據(jù)。磁盤(pán) IO 次數(shù)變少了,查詢數(shù)據(jù)的效率也就提高了。

這種數(shù)據(jù)結(jié)構(gòu)我們稱為 B 樹(shù),B 樹(shù)是一種多叉平衡查找樹(shù)

2.5 B + 樹(shù)

B + 樹(shù)和 B 樹(shù)最主要的區(qū)別在于非葉子節(jié)點(diǎn)是否存儲(chǔ)數(shù)據(jù)的問(wèn)題。

B 樹(shù):非葉子節(jié)點(diǎn)和葉子節(jié)點(diǎn)都會(huì)存儲(chǔ)數(shù)據(jù)。

B + 樹(shù):只有葉子節(jié)點(diǎn)才會(huì)存儲(chǔ)數(shù)據(jù),非葉子節(jié)點(diǎn)至存儲(chǔ)鍵值。葉子節(jié)點(diǎn)之間使用雙向指針連接,最底層的葉子節(jié)點(diǎn)形成了一個(gè)雙向有序鏈表。

wKgZomWH6eqAQJ23AAD6_jOyXoY723.jpg

正是因?yàn)?B + 樹(shù)的葉子節(jié)點(diǎn)是通過(guò)鏈表連接的,所以找到下限后能很快進(jìn)行區(qū)間查詢,比正常的中序遍歷快

3 索引的維護(hù)

當(dāng)你 insert 一條數(shù)據(jù)的時(shí)候,索引需要做出必要的操作來(lái)保證數(shù)據(jù)的有序型。一般自增數(shù)據(jù)直接在后面加就行了,特殊情況下如果數(shù)據(jù)加到了中間,就需要挪動(dòng)后面所有的數(shù)據(jù),這樣效率比較受影響。

最糟糕的情況,如果當(dāng)前的數(shù)據(jù)頁(yè)(頁(yè)是 mysql 存儲(chǔ)的最小單位)存滿了,需要申請(qǐng)一個(gè)新的數(shù)據(jù)頁(yè),這個(gè)過(guò)程被稱為頁(yè)分裂。如果造成了頁(yè)分裂的話,勢(shì)必會(huì)造成性能的影響。但是 mysql 并不是無(wú)腦的數(shù)據(jù)分裂,如果你是從中間進(jìn)行數(shù)據(jù)分裂的話,對(duì)于自增主鍵,會(huì)導(dǎo)致一半的性能浪費(fèi)。mysql 會(huì)根據(jù)你的索引的類(lèi)型,和追蹤插入數(shù)據(jù)的情況決定分裂的方式,一般都存在 mysql 數(shù)據(jù)頁(yè)的 head 里面,如果是零散的插入,會(huì)從中間分裂。如果是順序插入,一般是會(huì)選擇插入點(diǎn)開(kāi)始分裂,或者插入點(diǎn)往后幾行導(dǎo)致的。決定是否從中間分裂,還是從最后分裂。

wKgaomWH6eqAQBPPAABWAaoMjZ4820.jpg

如果插入的是不規(guī)則的數(shù)據(jù),沒(méi)法保證后一個(gè)值比前一個(gè)大,就會(huì)觸發(fā)上面說(shuō)的分裂邏輯,最后達(dá)到下面的效果

wKgaomWH6eqAUgxyAABWADVYiA8316.jpg

所以絕大多數(shù)情況下,我們都需要使用自增索引,除非需要業(yè)務(wù)自定義主鍵,最好能保證只有一個(gè)索引,且索引是唯一索引。這樣可以避免回表,導(dǎo)致查詢搜索兩棵樹(shù)。保證數(shù)據(jù)頁(yè)的有序性,可以更好的使用索引。

4 回表

通俗的講就是,如果索引的列在 select 所需獲得的列中(因?yàn)樵?mysql 中索引是根據(jù)索引列的值進(jìn)行排序的,所以索引節(jié)點(diǎn)中存在該列中的部分值)或者根據(jù)一次索引查詢就能獲得記錄就不需要回表,如果 select 所需獲得列中有大量的非索引列,索引就需要先找到主鍵,再到表中找到相應(yīng)的列的信息,這就叫回表。

要介紹回表自然就得介紹聚集索引和非聚集索引
InnoDB 聚集索引的葉子節(jié)點(diǎn)存儲(chǔ)行記錄,因此, InnoDB 必須要有,且只有一個(gè)聚集索引:

如果表定義了主鍵,則 PK 就是聚集索引;

如果表沒(méi)有定義主鍵,則第一個(gè)非空唯一索引(not NULL unique)列是聚集索引;

否則,InnoDB 會(huì)創(chuàng)建一個(gè)隱藏的 row-id 作為聚集索引;

wKgaomWH6eqAHcsYAAHOIx0S2D4408.jpg

當(dāng)我們使用普通索引查詢方式,則需要先搜索普通索引樹(shù),然后得到主鍵 ID 后,再到 ID 索引樹(shù)搜索一次。因?yàn)榉侵麈I索引的葉子節(jié)點(diǎn)里面,實(shí)際存的是主鍵的 ID。這個(gè)過(guò)程雖然用了索引,但實(shí)際上底層進(jìn)行了兩次索引查詢,這個(gè)過(guò)程就稱為回表。也就是說(shuō),基于非主鍵索引的查詢需要多掃描一棵索引樹(shù)。因此,我們?cè)趹?yīng)用中應(yīng)該盡量使用主鍵查詢。或者有高頻請(qǐng)求時(shí),合理建立聯(lián)合索引,防止回表。

5 索引覆蓋

一句話表達(dá)的話,是只需要在一棵索引樹(shù)上就能獲取 SQL 所需的所有列數(shù)據(jù),無(wú)需回表,速度更快。落實(shí)到 sql 上的話,只要執(zhí)行計(jì)劃里面的輸出結(jié)果 Extra 字段為 Using index 時(shí),能夠觸發(fā)索引覆蓋。

常見(jiàn)的優(yōu)化手段,就是上面提到的,將查詢的字段都建到索引里面,至于 dba 愿不愿意讓你建,那就需要你們自己 battle 了。

一般索引覆蓋適用的場(chǎng)景包括 全表 count 查詢優(yōu)化、列查詢回表、分頁(yè)回表。高版本的 mysql 已經(jīng)做了優(yōu)化,當(dāng)命中聯(lián)合索引的其中一個(gè)字段,另外一個(gè)是 id 的時(shí)候,會(huì)自動(dòng)優(yōu)化,無(wú)需回表。因?yàn)槎?jí)索引的葉子上存了 primary key,也算索引覆蓋,無(wú)需額外成本。

wKgZomWH6eqANqLZAAGvPpG5ERU612.jpg

6 最左匹配原則

簡(jiǎn)單來(lái)說(shuō),就是你使用 ‘xx%’的時(shí)候,符合條件的話也會(huì)使用索引。
如果是聯(lián)合索引的話,我舉個(gè)例子,創(chuàng)建一個(gè)(a,b)的聯(lián)合索引

wKgZomWH6eqAKngEAADqQYCxszo588.jpg

可以看到 a 的值是有順序的,1,1,2,2,3,3,而 b 的值是沒(méi)有順序的 1,2,1,4,1,2。但是我們又可發(fā)現(xiàn) a 在等值的情況下,b 值又是按順序排列的,但是這種順序是相對(duì)的。這是因?yàn)?MySQL 創(chuàng)建聯(lián)合索引的規(guī)則是首先會(huì)對(duì)聯(lián)合索引的最左邊第一個(gè)字段排序,在第一個(gè)字段的排序基礎(chǔ)上,然后在對(duì)第二個(gè)字段進(jìn)行排序。所以 b=2 這種查詢條件沒(méi)有辦法利用索引。舉個(gè)例子,我弄一個(gè)索引,
KEYidx_time_zone(time_zone,time_string) USING BTREE
執(zhí)行第一條 sql, 全表掃描

wKgaomWH6eqAPl0tAACjwUoqunU558.jpg

執(zhí)行第二條 sql,可以看到使用了索引。

wKgaomWH6eqAWQCIAACqsBSunPg262.jpg

再看兩條 sql,建立的索引是 KEYidx_time_zone(time_zone,time_string) USING BTREE

wKgZomWH6eqANODgAABNmxwiFRA244.jpg

wKgZomWH6eqAcOHDAADEiOvrC2k587.jpg

按照正常邏輯來(lái)說(shuō),第二條 sql 是不符合索引字段的順序的,應(yīng)該不能使用索引才對(duì),但是實(shí)際情況卻和我們期望的不太一樣,這是為啥呢?

從 mysql 被 oracle 收購(gòu)以后,mysql 加入了很多 oracle 以前的技術(shù),高版本 mysql 自動(dòng)優(yōu)化了 where 條件的先后順序。簡(jiǎn)單來(lái)說(shuō)就是查詢優(yōu)化器做了這一步操作,sql 會(huì)做預(yù)處理,那一條能更好的查詢就會(huì)使用那種規(guī)則。

順便提一下 mysql 的查詢優(yōu)化器能幫忙干的一些事

6.1 條件轉(zhuǎn)化

例如 where a=b and b=2,可以得到 a=2, 條件傳遞。最后的 sql 是 a=2 and b=2 > < = like 都可以傳遞

6.2 無(wú)效代碼的排除

例如 where 1=1 and a=2, 1=1 永遠(yuǎn)是正確的,所以最后會(huì)優(yōu)化成 a=2
在比如 where 1=0 永遠(yuǎn)是 false 的,這樣的也會(huì)被排除掉,整 sql 無(wú)效
或者非空字段 where a is null , 這樣的也會(huì)被排除

6.3 提前計(jì)算

包含數(shù)學(xué)運(yùn)算的部分,例如 where a= 1+2 會(huì)幫你算好,where a=3

6.4 存取類(lèi)型

當(dāng)我們?cè)u(píng)估一個(gè)條件表達(dá)式,MySQL 判斷該表達(dá)式的存取類(lèi)型。下面是一些存取類(lèi)型,按照從最優(yōu)到最差的順序進(jìn)行排列:

system 系統(tǒng)表,并且是常量表

const 常量表

eq_ref unique/primary 索引,并且使用的是’=’進(jìn)行存取

ref 索引使用’=’進(jìn)行存取

ref_or_null 索引使用’=’進(jìn)行存取,并且有可能為 NULL

range 索引使用 BETWEEN、IN、>=、LIKE 等進(jìn)行存取

index 索引全掃描

ALL 表全掃描

經(jīng)常看執(zhí)行計(jì)劃的,一眼就能看出來(lái)這是啥意思,舉個(gè)例子

where index_col=2 and normal_col =3 這里就會(huì)選用 index_col=2 會(huì)作為驅(qū)動(dòng)項(xiàng)。驅(qū)動(dòng)項(xiàng)的意思是指一個(gè) sql 選定他的執(zhí)行計(jì)劃的時(shí)候,可能有多條執(zhí)行路徑,一個(gè)是全表掃描,再過(guò)濾是否符合索引字段及非索引字段的值。另一種是通過(guò)索引字段,鍵值 = 2 找到對(duì)應(yīng)的索引樹(shù),過(guò)濾后的結(jié)果,再比較是否符合非索引字段的值。一般情況下,走索引都比全表掃描需要讀取磁盤(pán)的次數(shù)少,所以稱它為更好的執(zhí)行路徑,也就是通過(guò)索引字段,作為其驅(qū)動(dòng)表達(dá)式

6.5 范圍存取

簡(jiǎn)單來(lái)說(shuō),a in (1,2,3) 和 a=1 or a=2 or a=3 是一樣的,between 1 and 2 和 a>1 and a<2 也是一樣的, 無(wú)需可以優(yōu)化。

6.6 索引存取類(lèi)型

避免使用相同前綴的索引,也就是一個(gè)字段不要在多個(gè)索引上有相同的前綴。比如一個(gè)字段已經(jīng)建立了唯一索引,這個(gè)時(shí)候如果再給他建立一個(gè)聯(lián)合索引,會(huì)導(dǎo)致優(yōu)化器并不知道你要使用哪個(gè)索引?;蛘吣憬饲熬Y相同的一個(gè)單索引,一個(gè)聯(lián)合索引,就算你寫(xiě)上了條件,也不一定能用上聯(lián)合索引。當(dāng)然,可以 force,這就另說(shuō)了。

6.7 轉(zhuǎn)換

簡(jiǎn)單的表達(dá)式可以進(jìn)行轉(zhuǎn)換,比如 where -2 = a 會(huì)自動(dòng)變成 where a= -2 ,但是如果牽扯到數(shù)學(xué)運(yùn)算,就不能轉(zhuǎn)換了 比如 where 2= -a 這時(shí)候不會(huì)自動(dòng)轉(zhuǎn)成 where a =-2.

wKgaomWH6eqAIvkDAABDOADpxH4649.jpg

第二條 sql 就可以使用索引

wKgZomWH6eqAQo0lAACeFiL6Uho773.jpg

所以 我們?cè)陂_(kāi)發(fā)的過(guò)程中,需要注意 sql 的寫(xiě)法,自覺(jué)寫(xiě)成 where a=-2

6.8 and、union、order by、group by 等

1)and

and 條件后,如果都沒(méi)索引,掃描全表。有一個(gè)存取類(lèi)型更好,見(jiàn) 5.4 , 會(huì)使用存儲(chǔ)類(lèi)型更好的索引,如果都一樣,哪個(gè)索引先創(chuàng)建,用哪個(gè)。

2)union

union 每條語(yǔ)句單獨(dú)優(yōu)化

wKgZomWH6eqAViVnAABZKWPSit8910.jpg

這里就會(huì)分別執(zhí)行兩條 sql,用到索引,再合并結(jié)果集

3)order by

order by 會(huì)過(guò)濾無(wú)效排序,比如一個(gè)字段本來(lái)就有索引

wKgaomWH6eqANgU9AABhbtXPY50644.jpg

第二條 sql 和第一條的查詢效果是一樣的

wKgaomWH6eqAUfUjAABbtzZVG1o440.jpg

所以,寫(xiě) sql 的時(shí)候,不要寫(xiě)無(wú)用排序,比如 order by ‘xxx’ 這樣沒(méi)有意義。

4)group by

簡(jiǎn)單來(lái)說(shuō) group by 的字段,有索引會(huì)走索引,group by a order by a 這里的 order by 等于沒(méi)寫(xiě),結(jié)果集已經(jīng)是排序完畢的了,參考 6.8-3 order by
select distinct col_a from table a 等價(jià)于 select col_a from a group by col_a

7 索引下推

主要的核心點(diǎn)就在于把數(shù)據(jù)篩選的過(guò)程放在了存儲(chǔ)引擎層去處理,而不是像之前一樣放到 Server 層去做過(guò)濾。

如果在一張表上,name 和 age 都建立索引,查詢條件為 where name like ‘xx%’ and age=11, 在低版本的 mysql (5.6 以下) 的根據(jù)索引的最左匹配原則,可以得到放棄了 age,只根據(jù) name 過(guò)濾數(shù)據(jù)。根據(jù) name 拿到所有的 id 之后,再根據(jù) id 回表。

高版本 mysql 里,沒(méi)有忽略 age 這個(gè)屬性,帶著 age 屬性過(guò)濾,直接過(guò)濾掉了 age 為 11 的數(shù)據(jù),假設(shè)不根據(jù) age 過(guò)濾的數(shù)據(jù)為 10 條,過(guò)濾后只剩 3 條,就少了 7 次回表。減少了 io 會(huì)大量減少性能消耗

8 小表驅(qū)動(dòng)大表

小表驅(qū)動(dòng)大表,也是我們聽(tīng)?wèi)T了的話了,其含義主要是指小表的數(shù)據(jù)集驅(qū)動(dòng)大表的數(shù)據(jù)集,減少連接次數(shù)。打個(gè)比方:

表 A 有 1w 數(shù)據(jù),表 B 有 100w 數(shù)據(jù),如果 A 表作為驅(qū)動(dòng)表,處于循環(huán)的外層,那么只需要 1w 次的連接即可。如果 B 表在外層,那么則需要循環(huán) 100w 次。

下面我們實(shí)際測(cè)試看看,準(zhǔn)備環(huán)境 mysql 5.7+

wKgZomWH6eqALeCrAAAJJDJPH4U424.jpg

準(zhǔn)備兩張表,一張表 ib_asn_d 數(shù)據(jù) 9175, 一張表 bs_itembase_ext_attr 數(shù)據(jù) 1584115,都在商品編碼字段上有索引。

首先小表驅(qū)動(dòng)大表

wKgZomWH6eqANVfdAAAd5n8JGCE722.jpg

多次反復(fù)測(cè)試,執(zhí)行時(shí)間大概 7 秒。
接下來(lái)看看大表驅(qū)動(dòng)小表。

wKgaomWH6eqAXisGAAAxvneZQRQ998.jpg

將近 300 秒,不是一個(gè)量級(jí)的。
接下來(lái)分別分析執(zhí)行計(jì)劃,執(zhí)行計(jì)劃里第一條就是驅(qū)動(dòng)表。

wKgaomWH6eqAY4CPAACtD6J7d2I383.jpg

小表驅(qū)動(dòng)大表,大表用了索引,小表全表掃描,只掃描 8000 多行

wKgZomWH6eqALZB5AABRuf8jwJw841.jpg

大表驅(qū)動(dòng)小表,大表全表掃描,需要掃描 147w 行。
經(jīng)過(guò)多次測(cè)試得出了結(jié)論:

當(dāng)使用 left join 時(shí),左表是驅(qū)動(dòng)表,右表是被驅(qū)動(dòng)表;

當(dāng)使用 right join 時(shí),右表是驅(qū)動(dòng)表,左表是被驅(qū)動(dòng)表;

當(dāng)使用 inner join 時(shí),mysql 會(huì)選擇數(shù)據(jù)量比較小的表作為驅(qū)動(dòng)表,大表作為被驅(qū)動(dòng)表;

驅(qū)動(dòng)表索引不生效,非驅(qū)動(dòng)表索引生效

保證小表是驅(qū)動(dòng)表很重要。

9 總結(jié)

覆蓋索引:如果查詢條件使用的是普通索引(或是聯(lián)合索引的最左原則字段),查詢結(jié)果是聯(lián)合索引的字段或是主鍵,不用回表操作,直接返回結(jié)果,減少 IO 磁盤(pán)讀寫(xiě)讀取整行數(shù)據(jù),所以高頻字段建立聯(lián)合索引是很有必要的

最左前綴:聯(lián)合索引的最左 N 個(gè)字段,也可以是字符串索引的最左 M 個(gè)字符。建立索引的時(shí)候,注意左前綴不要重復(fù),避免查詢優(yōu)化器無(wú)法判定如何使用索引

索引下推:name like ‘hello%’and age >10 檢索,MySQL 5.6 版本之前,會(huì)對(duì)匹配的數(shù)據(jù)進(jìn)行回表查詢。5.6 版本后,會(huì)先過(guò)濾掉 age<10 的數(shù)據(jù),再進(jìn)行回表查詢,減少回表率,提升檢索速度。







審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    2983

    瀏覽量

    106499
  • 磁盤(pán)
    +關(guān)注

    關(guān)注

    1

    文章

    386

    瀏覽量

    25567
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    840

    瀏覽量

    27332
  • HASH函數(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    5784

原文標(biāo)題:理解Mysql索引原理及特性

文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    MySQL索引的創(chuàng)建與刪除

    MySQL——索引技巧以及注意事項(xiàng)
    發(fā)表于 10-31 09:27

    詳解mysql索引

    mysql索引簡(jiǎn)介
    發(fā)表于 04-13 06:50

    mysql索引使用技巧哪些?

    mysql索引使用技巧
    發(fā)表于 05-20 06:09

    基于MySQL索引的壓力測(cè)試

    MySQL - 基于索引的壓力測(cè)試
    發(fā)表于 06-13 07:57

    MySQL索引使用優(yōu)化和規(guī)范

    MySQL - 索引使用優(yōu)化和規(guī)范
    發(fā)表于 06-15 16:01

    MySQL索引、事務(wù)、視圖介紹

    MySQL--索引、事務(wù)、視圖
    發(fā)表于 06-15 07:05

    MySQL索引使用原則

    一般來(lái)說(shuō), MySQL 中的 B-Tree 索引的物理文件大多都是以 Balance Tree 的結(jié)構(gòu)來(lái)存儲(chǔ)的,也就是所有實(shí)際需要的數(shù)據(jù)都存放于 Tree 的 Leaf Node(葉子節(jié)點(diǎn)) ,而且
    的頭像 發(fā)表于 02-11 15:17 ?2843次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>索引</b>使用原則

    MySQL索引的使用問(wèn)題

    一、前言 在MySQL中進(jìn)行SQL優(yōu)化的時(shí)候,經(jīng)常會(huì)在一些情況下,對(duì)MySQL能否利用索引一些迷惑。譬如:1、MySQL 在遇到范圍查詢條
    的頭像 發(fā)表于 01-06 16:13 ?1716次閱讀

    關(guān)于MySQL索引的分類(lèi)與原理及本質(zhì)解析

    索引,可能讓好很多人望而生畏,畢竟每次面試時(shí)候 MySQL索引一定是必問(wèn)內(nèi)容,哪怕先撇開(kāi)面試,就在平常的開(kāi)發(fā)中,對(duì)于 SQL 的優(yōu)化也而是重中之重。
    的頭像 發(fā)表于 04-03 11:56 ?1738次閱讀
    關(guān)于<b class='flag-5'>MySQL</b>中<b class='flag-5'>索引</b>的分類(lèi)與原理及本質(zhì)解析

    一百道關(guān)于MySQL索引解答

    數(shù)據(jù)庫(kù) 1. MySQL索引使用哪些注意事項(xiàng)呢? 可以從三個(gè)維度回答這個(gè)問(wèn)題:索引哪些情況會(huì)失效,索引不適合哪些場(chǎng)景,
    的頭像 發(fā)表于 06-13 15:51 ?2258次閱讀

    MySQL高級(jí)進(jìn)階:索引優(yōu)化

    MySQL官方對(duì)于索引的定義:索引是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。
    的頭像 發(fā)表于 06-11 11:13 ?746次閱讀
    <b class='flag-5'>MySQL</b>高級(jí)進(jìn)階:<b class='flag-5'>索引</b>優(yōu)化

    MySQL索引的常用知識(shí)點(diǎn)

    索引結(jié)構(gòu):B+樹(shù) 索引其實(shí)是一種數(shù)據(jù)結(jié)構(gòu) 注意B+樹(shù)是MySQL索引默認(rèn)的結(jié)構(gòu);一張表至少有一個(gè)索引(主鍵
    的頭像 發(fā)表于 09-30 16:43 ?593次閱讀

    索引是什么意思 優(yōu)缺點(diǎn)哪些

    的數(shù)據(jù)結(jié)構(gòu),以協(xié)助快速查詢、更新數(shù)據(jù)庫(kù)表中數(shù)據(jù)。索引的實(shí)現(xiàn)通常使用B樹(shù)及其變種B+樹(shù)。更通俗的說(shuō),索引就相當(dāng)于目錄。為了方便查找書(shū)中的內(nèi)容,通過(guò)對(duì)內(nèi)容建立索引形成目錄。而且索引是一個(gè)文
    的頭像 發(fā)表于 10-09 10:19 ?3616次閱讀

    導(dǎo)致MySQL索引失效的情況以及相應(yīng)的解決方法

    導(dǎo)致MySQL索引失效的情況以及相應(yīng)的解決方法? MySQL索引的目的是提高查詢效率,但有些情況下索引可能會(huì)失效,導(dǎo)致查詢變慢或效果不如預(yù)期
    的頭像 發(fā)表于 12-28 10:01 ?966次閱讀

    一文了解MySQL索引機(jī)制

    接觸MySQL數(shù)據(jù)庫(kù)的小伙伴一定避不開(kāi)索引,索引的出現(xiàn)是為了提高數(shù)據(jù)查詢的效率,就像書(shū)的目錄一樣。 某一個(gè)SQL查詢比較慢,你第一時(shí)間想到的就是“給某個(gè)字段加個(gè)索引吧”,那么
    的頭像 發(fā)表于 07-25 14:05 ?478次閱讀
    一文了解<b class='flag-5'>MySQL</b><b class='flag-5'>索引</b>機(jī)制