Sql索引優(yōu)化—轉(zhuǎn)載

數(shù)據(jù)庫(kù)索引使用方式

使用索引是提高數(shù)據(jù)庫(kù)查詢效率的主要方式,下面從索引結(jié)構(gòu),索引類型,索引操作,命中索引幾個(gè)方面來(lái)介紹索引。

一、索引結(jié)構(gòu)

mysql5.5以上的默認(rèn)存儲(chǔ)引擎innodb,只顯式支持BTree( 事實(shí)上從數(shù)據(jù)結(jié)構(gòu)上來(lái)講是B+樹(shù),mysql稱之為BTree)索引,對(duì)于頻繁訪問(wèn)的表,innodb會(huì)建立自適應(yīng)hash索引,

即在B樹(shù)索引基礎(chǔ)上建立hash索引,可以顯著提高查找效率,用戶是無(wú)法自己指定的,除此之外還有Hash索引和全文索引(fullText索引)。?


BTree索引?

BTree,顧名思義,就是所有的索引節(jié)點(diǎn)都按照balance tree的數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)。BTree結(jié)構(gòu)可以顯著減少定位記錄時(shí)所經(jīng)歷的中間過(guò)程,從而加快存取速度。

Btree中,每個(gè)結(jié)點(diǎn)包含:

1、本結(jié)點(diǎn)所含關(guān)鍵字的個(gè)數(shù);

2、指向父結(jié)點(diǎn)的指針;

3、關(guān)鍵字;

4、指向子結(jié)點(diǎn)的指針;

更詳細(xì)的B+樹(shù)介紹參考https://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html


Hash索引?

Hash 索引由于使用了hash表結(jié)構(gòu),其檢索效率很高,索引的檢索可以一次定位,不像B+樹(shù)索引需要從根節(jié)點(diǎn)到枝節(jié)點(diǎn),

所以 Hash 索引的查詢效率要遠(yuǎn)高于 B+樹(shù) 索引。但是,Hash索引的使用范圍非常有限。

? ? 1.在MySQL中,只有HEAP/MEMORY引擎表才能支持哈希索引,InnoDB引擎的自適應(yīng)哈希索引(adaptive hash index)不

? ?能在創(chuàng)建索引時(shí)指定。

? ?2.Hash索引僅支持=,>=,<=這幾種條件運(yùn)算,不支持排序,范圍內(nèi)查找,like等查詢。

? ?3.Hash索引不支持組合索引中部分索引的查找。

? ?4.當(dāng)Hash值重復(fù)較多時(shí),索引速度可能不如BTree索引。


FullText索引

Full-text索引就是我們常說(shuō)的全文索引,他的存儲(chǔ)結(jié)構(gòu)也是Btree。主要是為了解決在我們需要用like查詢的低效問(wèn)題。

只能解決’xxx%’的like查詢。如:字段數(shù)據(jù)為ABCDE,索引建立為A、AB、ABC、ABCD、ABCDE五個(gè)。

二、索引類型

索引一般有:普通索引,唯一索引,復(fù)合索引這幾種類型。

唯一索引:唯一索引要求字段中不會(huì)出現(xiàn)重復(fù)數(shù)據(jù)。

復(fù)合索引:將多個(gè)字段組合起來(lái)作為索引,必須使用到該索引中的第一個(gè)字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用。

三、索引操作

建立索引:

createindex索引名on表名(索引字段名)

建立唯一索引:

createuniqueindex索引名on表名(索引字段名)

建立復(fù)合索引:

createindex索引名on表名(索引字段名1,索引字段名2...)

查看表中索引:

showindexfrom表名

刪除索引:

dropindex索引名on表名

查看索引是否命中

Mysql:當(dāng)結(jié)果的type為 index時(shí)索引命中

explain+sql語(yǔ)句

Oracle:

explainplanfor+sql語(yǔ)句

四、命中索引

1.避免判斷null值

應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:

selectidfromtwherenumisnull

可以在num上設(shè)置默認(rèn)值0,確保表中num列沒(méi)有null值,然后這樣查詢:

selectidfromtwherenum=0

2. 避免不等值判斷

應(yīng)盡量避免在where子句中使用!=或<>操作符,否則引擎將放棄使用索引而進(jìn)行全表掃描。

3.避免使用or邏輯

應(yīng)盡量避免在where子句中使用 or 來(lái)連接條件,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,

selectidfromtwherenum=1ornum=2

可以使用union all來(lái)進(jìn)行查詢來(lái)命中索引如:

selectidfromtwherenum=1 unionall selectidfromtwherenum=2

4 .慎用in和not in邏輯

in和 not in 也要慎用,否則會(huì)導(dǎo)致全表掃描,如:

selectidfromt1wherenumin(selectidfromt2whereid>10)

此時(shí)外層查詢會(huì)全表掃描,不使用索引。可以修改為:

selectidfromt1,(selectidfromt1whereid>10)t2wheret1.id=t2.id

此時(shí)索引被使用,可以明顯提升查詢效率。

5.注意模糊查詢

下面的查詢也將導(dǎo)致全表掃描:

selectidfromtwherenamelike'%abc%'

不要在like條件左邊加'%',這樣不會(huì)走索引模糊查詢?nèi)绻潜匾獥l件時(shí),可以使用

selectidfromtwherenamelike'abc%'

來(lái)實(shí)現(xiàn)模糊查詢,此時(shí)索引將被使用。如果頭匹配是必要的,可以使用elasticsearch等全文搜索引擎。

6.避免查詢條件中字段計(jì)算

應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:

selectidfromtwherenum/2=100

應(yīng)改為:

selectidfromtwherenum=100*2

7.避免查詢條件中對(duì)字段進(jìn)行函數(shù)操作

應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:

selectidfromtwheresubstring(name,1,3)='abc'

name以abc開(kāi)頭的id

應(yīng)改為:

selectidfromtwherenamelike'abc%'

8. “=”左邊避免表達(dá)式運(yùn)算

不要在where子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則系統(tǒng)將可能無(wú)法正確使用索引。

9.組合索引使用

在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個(gè)字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用,并且應(yīng)盡可能的讓字段順序與索引順序相一致。

10exists

很多時(shí)候用exists代替 in 是一個(gè)好的選擇:

selectnumfromawherenumin(selectnumfromb)

用下面的語(yǔ)句替換:

selectnumfromawhereexists(select1frombwherenum=a.num)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容