(一)MySQL优化之索引优化
一、索引的概念
我們知道,在查詢過程中,如果被查詢的表沒有索引,數(shù)據(jù)庫會(huì)進(jìn)行全表掃描,而如果添加了相應(yīng)的索引,數(shù)據(jù)庫會(huì)根據(jù)索引直接查找符合條件的數(shù)據(jù)。因此,索引的存在會(huì)大大提高查詢效率。而索引其實(shí)就是一個(gè)特殊文件(InnoDB中索引是表空間的一部分),它包含碰上對(duì)表中所有記錄的引用指針。
二、索引的分類
索引可以分為兩種:聚簇索引和非聚簇索引。
(一)聚簇索引
聚簇索引是按照每張表的主鍵構(gòu)造一顆B+樹,同時(shí)葉子節(jié)點(diǎn)中存放的就是整張表的行記錄數(shù)據(jù),也將聚集索引的葉子節(jié)點(diǎn)稱為數(shù)據(jù)頁。這個(gè)特性決定了索引組織表中數(shù)據(jù)也是索引的一部分,每張表只能擁有一個(gè)聚簇索引。
(二)非聚簇索引
非聚簇索引使用B+Tree作為索引結(jié)構(gòu),葉節(jié)點(diǎn)的data域存放的是數(shù)據(jù)記錄的地址。查詢先通過索引查找到符合條件的地址,然后通過地址查再找數(shù)據(jù)。
(三)兩種索引的區(qū)別
1.聚簇索引是和數(shù)據(jù)在一起的,通過索引即可一次性查詢出數(shù)據(jù)。
2.非聚簇索引索引文件和數(shù)據(jù)是獨(dú)立的,查詢會(huì)先查找到符合條件的索引,通過地址進(jìn)行二次查找表中的數(shù)據(jù)。
3.聚簇索引的效率比非聚簇索引的高。
4.由于節(jié)子節(jié)點(diǎn)(數(shù)據(jù)頁)只能按照一顆B+樹排序,故一張表只能有一個(gè)聚簇索引。輔助索引的存在不影響聚簇索引中數(shù)據(jù)的組織,所以一張表可以有多個(gè)輔助索引。
(四) 應(yīng)用
1.InnoDB存儲(chǔ)引擎
1.1 主鍵索引
InnoDB存儲(chǔ)引擎主鍵索引使用的是聚簇索引,如果沒有定義主鍵,innodb會(huì)選擇非空的唯一索引代替。如果沒有這樣的索引,innodb會(huì)隱式的定義一個(gè)主鍵來作為聚簇索引。
優(yōu)點(diǎn):
1.數(shù)據(jù)訪問更快,因?yàn)榫鄞厮饕龑⑺饕蛿?shù)據(jù)保存在同一個(gè)B+樹中,因此從聚簇索引中獲取數(shù)據(jù)比非聚簇索引更快
2.聚簇索引對(duì)于主鍵的排序查找和范圍查找速度非常快
缺點(diǎn):
1.插入速度嚴(yán)重依賴于插入順序,按照主鍵的順序插入是最快的方式,否則將會(huì)出現(xiàn)頁分裂,嚴(yán)重影響性能。因此,對(duì)于InnoDB表,我們一般都會(huì)定義一個(gè)自增的ID列為主鍵
2.更新主鍵的代價(jià)很高,因?yàn)閷?huì)導(dǎo)致被更新的行移動(dòng)。因此,對(duì)于InnoDB表,我們一般定義主鍵為不可更新。
1.2 輔助索引(又叫非聚簇索引)
InnoDB的所有輔助索引都引用主鍵作為data域。
InnoDB 表是基于聚簇索引建立的。因此InnoDB 的索引能提供一種非常快速的主鍵查找性能。不過,它的輔助索引(Secondary Index, 也就是非主鍵索引)也會(huì)包含主鍵列,所以,如果主鍵定義的比較大,輔助索引也將很大。如果想在表上定義 、很多索引,則爭取盡量把主鍵定義得小一些。InnoDB 不會(huì)壓縮索引。
文字符的ASCII碼作為比較準(zhǔn)則。聚集索引這種實(shí)現(xiàn)方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。
不同存儲(chǔ)引擎的索引實(shí)現(xiàn)方式對(duì)于正確使用和優(yōu)化索引都非常有幫助,例如知道了InnoDB的索引實(shí)現(xiàn)后,就很容易明白:
1、為什么不建議使用過長的字段作為主鍵,因?yàn)樗休o助索引都引用主索引,過長的主索引會(huì)令輔助索引變得過大。再例如,
2、用非單調(diào)的字段作為主鍵在InnoDB中不是個(gè)好主意,因?yàn)镮nnoDB數(shù)據(jù)文件本身是一顆B+Tree,非單調(diào)的主鍵會(huì)造成在插入新記錄時(shí)數(shù)據(jù)文件為了維持B+Tree的特性而頻繁的分裂調(diào)整,十分低效,而使用自增字段作為主鍵則是一個(gè)很好的選擇。
2.MyISAM存儲(chǔ)引擎
MyISAM索引文件和數(shù)據(jù)文件是分離的,索引文件僅保存數(shù)據(jù)記錄的地址。
在MyISAM中,主索引和輔助索引(Secondary key)在結(jié)構(gòu)上沒有任何區(qū)別,只是主索引要求key是唯一的,而輔助索引的key可以重復(fù)。
由此可知,MyISAM存儲(chǔ)引擎的索引都是非聚簇索引。但是由于其主鍵索引和輔助索引存儲(chǔ)的都是鍵的地址,兩者是獨(dú)立的索引樹,因此與InnoDB不同的是,輔助索引不用依賴和訪問主索引的索引樹。
參考博客:https://www.cnblogs.com/jiawen010/p/11805241.html
三、索引的優(yōu)缺點(diǎn)
(一)優(yōu)點(diǎn)
1.唯一索引可以保證數(shù)據(jù)唯一性。
2.添加索引可以大大提高查詢效率。
3.加速表與表之間的連接。
4.通過使用索引,可以在查詢過程中,使用優(yōu)化隱藏器提高系統(tǒng)性能。
(二)缺點(diǎn)
1.創(chuàng)建和維護(hù)索引要消耗時(shí)間,而且這種時(shí)間會(huì)隨著數(shù)據(jù)量的增加而增加。
2.索引會(huì)占用物理空間,聚簇索引占用的空間會(huì)更大。在InnoDB中,由于輔助索引B+樹的葉子上會(huì)存儲(chǔ)主鍵數(shù)據(jù),因此主鍵長度也要盡量定義小一些。
3.由于增、刪、改操作的時(shí)候,索引也要?jiǎng)討B(tài)維護(hù),這樣也就降低了數(shù)據(jù)維護(hù)的速度。
四、創(chuàng)建索引的注意事項(xiàng)
一般來說,以下字段適合創(chuàng)建索引:
1.經(jīng)常查詢的字段:可以提高查詢速度。
2.主鍵字段:強(qiáng)調(diào)主鍵的唯一性,有助于組織表數(shù)據(jù)的排列結(jié)構(gòu)。
3.經(jīng)常使用的連接鍵:加快連接速度。
4.經(jīng)常需要進(jìn)行范圍查詢的列:因?yàn)樗饕怯行虻?#xff0c;其指定的范圍也是連續(xù)的。
5.經(jīng)常使用的排序字段:因?yàn)樗饕怯行虻?#xff0c;可以利用索引的排序加快查詢速度。
6.常用的where語句過濾條件。
一般來說,以下字段不太適合創(chuàng)建索引:
1.查詢中很少使用的列:額外的索引會(huì)增大磁盤的需求,也會(huì)額外增加維護(hù)成本。
2.有大量重復(fù)數(shù)據(jù)的字段:對(duì)查詢并沒有明顯的效果。
3.對(duì)于text,image,bit數(shù)據(jù)類型字段:這些列的數(shù)據(jù)量太大,可是我們查詢中一般只截取使用其中的一小段數(shù)據(jù)。
4.對(duì)于修改遠(yuǎn)遠(yuǎn)大于檢索需求的列,不應(yīng)該建立索引。即使創(chuàng)建索引會(huì)增加查詢效率,但是大大降低修改的性能,增加維護(hù)成本。
五、Mysql索引的類型和創(chuàng)建
這里不在過多贅述,請(qǐng)自行百度。
要說明的兩點(diǎn)是
1.組合索引根據(jù)最左前綴的規(guī)則,查詢會(huì)從最左邊的索引字段開始組合。如果查詢中沒有使用索引中最左側(cè)的字段,將不會(huì)使用該組合索引。
六、Mysql索引優(yōu)化
優(yōu)化不是一成不變的,版本不同,優(yōu)化也有可能會(huì)不一樣。以下僅供參考:
1.范圍字段多使用聚簇索引:
因?yàn)榫鄞厮饕恍枰檎业剿钄?shù)據(jù)的開頭和結(jié)尾即可,而非聚簇索引要查到每一項(xiàng)數(shù)據(jù)對(duì)應(yīng)的頁碼,再根據(jù)頁碼查找具體數(shù)據(jù)。2.少數(shù)不同值的列推薦使用聚類索引;
3.頻繁修改更新的列推薦使用非聚集索引;
4.where條件中,字段類型不匹配也不會(huì)使用索引;
比如SKU為8位數(shù)字組成的字符串,如果用 SKU='12345678’會(huì)使用索引,但是使用 SKU = 12345678 則不會(huì)使用索引。
5.LIKE模糊查詢
索引根據(jù)最左前綴原則,右側(cè)模糊查詢可以使用索引,左模糊不行。例如:假設(shè)字段CLOUMN_1有索引,那么 CLOUMN_1 LIKE 'ABCD%' 可以使用索引; CLOUMN_1 LIKE '%ABCD' 以及 CLOUMN_1 LIKE '%ABCD%' 不能使用索引。6.使用短索引
如果列的值都比較長,如果前10或20個(gè)字符多數(shù)值是唯一的,就不需要對(duì)整個(gè)列的數(shù)據(jù)進(jìn)行索引。短索引不僅可以提高查詢速度,還可以節(jié)省磁盤和IO操作。7.索引列排序
Mysql查詢時(shí)只會(huì)使用一個(gè)索引,如果where條件中已經(jīng)使用了索引,那么order by中的列是不會(huì)使用索引的。 因此如果默認(rèn)排序可以符合要求的情況下,不要使用排序操作; 盡量不要包含多個(gè)列的排序,如果需要最好給這些列創(chuàng)建合適的復(fù)合索引。8.where語句中,不要在索引列上使用函數(shù)或進(jìn)行運(yùn)算
如果對(duì)索引列進(jìn)行運(yùn)算或使用函數(shù),會(huì)導(dǎo)致索引失效。
9.where條件中使用<> 或 != 也會(huì)做全表掃描,IS NULL/ IS NOT NULL 有時(shí)也會(huì)使索引失效
索引失效一般是由于mysql優(yōu)化器會(huì)對(duì)查詢的數(shù)據(jù)做一個(gè)數(shù)量的預(yù)估,如果我們用 is null,有空字段的索引一般是非聚簇索引。這種索引我們進(jìn)行一次查詢后,得到的是聚簇索引的主鍵,然后我們再進(jìn)行回表,才能得到數(shù)據(jù),這樣優(yōu)化器會(huì)根據(jù)空值的多少,自動(dòng)選擇開銷比較小的方案進(jìn)行優(yōu)化。比如我們空值比較少,這時(shí)非聚簇索引查找的數(shù)據(jù)比較精準(zhǔn),開銷也比較少,mysql就會(huì)使用索引進(jìn)行查詢。反之,如果空值比較多,這樣我們?nèi)绻褂镁鄞厮饕炔樵儩M足條件的主鍵,然后再通過大量的回表操作,才能得到我們想要的查詢結(jié)果,頻繁的IO就會(huì)造成性能開銷較大,mysql就會(huì)選擇不走索引的查詢方式。也就是說能不能用到索引,mysql是根據(jù)具體情況來決定的。
10.盡量避免使用OR來連接條件,這樣也會(huì)導(dǎo)致索引失效。
如果查詢語句的條件中,我們必須使用OR,我們可以采用union all來代替,比如:
select cname from t where id = 10 or id = 20; -- 我們可以改寫為 select cname from t where id = 10 union all select cname from t where id = 20;11. in 和 not in 也要慎用;
12.如果過濾的數(shù)值是連續(xù)的,能用between就不要用in;
13.如果條件中使用了變量,mysql也會(huì)放棄索引,進(jìn)行全表掃描;
因?yàn)閟ql只有在運(yùn)行時(shí),才會(huì)解析變量值,而優(yōu)化器是在執(zhí)行器之前運(yùn)行的。這樣優(yōu)化器就無法獲得變量的值,因而無法做為索引過濾輸入項(xiàng)。不過,我們可以強(qiáng)制查詢使用索引,比如:
select cname from t where id = $sid; -- 可以使用下面的sql進(jìn)行優(yōu)化: select cname from t with(index(索引名)) where id = $sid;14.在使用復(fù)合索引時(shí),必須使用到該索引的第一個(gè)字段做為條件才能保證查詢過程使用該復(fù)合索引。盡量保持條件字段順序與索引字段順序一致。
15.在優(yōu)化過程中,很多時(shí)候會(huì)用exists 代替in。
16.字段有大量重復(fù)數(shù)據(jù)的時(shí)候不建議建立索引,即使建立索引,mysql一般也不會(huì)使用索引,即使使用對(duì)性能也影響不大。如果數(shù)據(jù)量比較大,也會(huì)增加維護(hù)成本。
17.索引并不是越多越好,索引能提高查詢效率,但也同時(shí)降低了增、刪、改的效率,因?yàn)閕nsert、select有時(shí)可能會(huì)重建索引。一個(gè)表的索引數(shù)一般不超過6個(gè)。
總結(jié)
以上是生活随笔為你收集整理的(一)MySQL优化之索引优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VC动态数组实现
- 下一篇: access mysql oracle数