【MySQL】9.索引&單表查詢優(yōu)化

0. 什么是索引?

在數(shù)據(jù)之外筒严,數(shù)據(jù)庫系統(tǒng)維護著一種幫助快速獲取數(shù)據(jù)的有序的數(shù)據(jù)結(jié)構(gòu)丹泉,這種數(shù)據(jù)結(jié)構(gòu)實現(xiàn)了高級查找算法,以某種方式指向數(shù)據(jù)鸭蛙。索引會影響查找和排序的效率摹恨。

一般來說索引本身也很大,在不能全部存在內(nèi)存中的情況下娶视,會以索引鍵的形式存儲在磁盤上晒哄。

一、優(yōu)劣

1. 優(yōu)勢

  1. 對數(shù)據(jù)進行索引
    提高查找效率歇万,降低數(shù)據(jù)庫 IO 成本揩晴。
  2. 對數(shù)據(jù)進行排序
    降低排序成本和 CPU 消耗。

2. 劣勢

  1. 索引實際上也是存于表中贪磺,記錄索引的字段并指向?qū)嶓w的記錄硫兰,同樣占用空間;
  2. 對數(shù)據(jù)進行更新(增刪改)寒锚,每次更新索引字段等信息也需要更新劫映,造成額外負(fù)擔(dān)违孝;
  3. 索引不是一勞永逸,而是要不斷的調(diào)整泳赋。

3. 適合使用索引的場景

  1. 主鍵和唯一約束都會默認(rèn)創(chuàng)建唯一索引雌桑;
  2. 頻繁查詢的字段適合使用索引;
  3. 連表查詢的關(guān)聯(lián)字段祖今,外鍵關(guān)心建立索引屿储;
  4. 排序字段可用索引降低消耗;
  5. 統(tǒng)計或分組字段適合索引疹味。

4. 不適合索引的場景

  1. 頻繁更新數(shù)據(jù)的字段不適合使用索引蚪黑;
  2. 沒用用于查找和排序的字段不適合索引;
  3. 記錄太少徐绑,沒必要建索引
  4. 重復(fù)值過多的字段不適合索引邪驮,如性別,即使建了索引也沒有實際效果

二傲茄、索引分類

  1. 單值索引
    即一個索引對應(yīng)一個列
  2. 復(fù)合索引
    一個索引對應(yīng)多個列
  3. 唯一索引
    索引列須是唯一

三毅访、語法

  1. 創(chuàng)建索引
create index [unique] indexName on tableName(columnName(length))
#或
alter table tableName add [unique] index 【indexName】(columnName)
#indexName 索引名
#tableName 表名
#columnName 列名
#length 列的長度
  1. 刪除索引
drop index [indexName] on table
  1. 查看索引
show index from tableName

四、主要索引結(jié)構(gòu)

  1. B-Tree 索引
  2. Hash 索引
  3. Full-text 索引
  4. R-Tree 索引

五盘榨、索引分析

索引失效不僅會使查詢喻粹、排序變慢,還會使行鎖變表鎖较曼,所以一定要避免索引失效

1. where后使用索引的原則

  1. 最好能到到全值匹配
    意思就是查詢能夠完全匹配索引磷斧,包括列和順序,比如:
    創(chuàng)建了 idx_a_b_c捷犹,那么最好查詢的時候也能按照 a弛饭,b,c 的進行查找萍歉。

  2. 最佳左前綴法則
    查詢要從索引的最左側(cè)開始侣颂,并且中間不能斷,比如:
    創(chuàng)建了 idx_a_b_c枪孩,那么按照 a 查詢憔晒,或者按照 a、b 查詢蔑舞,都是滿足最佳最前綴法則的拒担;
    而按照 b、c 或者 a攻询、c 或者 c 查詢都違反了此原則从撼;
    a、c 還好钧栖,至少還有 a 可以使用索引低零,b婆翔、c 和 c 則索引完全用不上。

  3. 不要在索引列上做以下操作:計算掏婶,使用函數(shù)啃奴,類型轉(zhuǎn)換(自動或手動)
    這類操作會導(dǎo)致索引失效,轉(zhuǎn)向全表掃描

  4. 字符串不加單引號會導(dǎo)致索引失效
    例如雄妥,varchar 類型的字段 a最蕾,where a=1 和 where a='1'查詢結(jié)果一樣,但是 a=1 會導(dǎo)致 mysql 隱式的類型轉(zhuǎn)換老厌,導(dǎo)致索引失效
    用單引號揖膜,不要在用雙引號了

  5. 范圍條件搜索右側(cè)都會失效
    例如,創(chuàng)建 idx_a_b_c梅桩,
    select * from t1 where a=1 and b>1 and c=1,這條語句中拜隧,a=1 是 ref 類型的宿百,b>1是 range 類型的,這兩個都用到了索引洪添,但是 c=1 就無法使用索引了垦页,因為 b>1 被打斷了。此時干奢,b 用到了索引痊焊,但是是用來排序,所以是 range 級別
    in 也是范圍查找忿峻。

  6. 不等于(!= 或 <>)會導(dǎo)致索引失效薄啥,從而全表掃描

  7. is not null 會導(dǎo)致索引失效
    盡量索引字段有 null,可以增加空的默認(rèn)值逛尚,例如''垄惧。

  8. like '%...' 或?qū)е滤饕?br> '%....' 會導(dǎo)致索引失效(索引類型變成 all,全表掃描)绰寞,但 '....%' 仍是 range 類型索引(雖然是 range到逊,但是這種比較特殊,和 >,< 不同滤钱,它不會打斷索引觉壶,也就是說,他后邊的索引還可以用)件缸。

  9. 盡量使用覆蓋索引铜靶,減少使用 select *
    例如 idx_a_b_c,select a,b,c 就可以形成覆蓋索引(最好按順序停团,可以少旷坦,但不可多于a,b,c)掏熬,select * 則不行。

解決方法:利用覆蓋索引秒梅,例如:select id from t1 where a like '%123%'(id 是主鍵旗芬,有唯一索引),這個查詢類型是 index捆蜀,優(yōu)于 all疮丛。

  1. or 會導(dǎo)致索引失效,應(yīng)少用
    解決辦法:拆成多個語句辆它,將查詢結(jié)果合并即可誊薄。

  2. 創(chuàng)建復(fù)合索引的時候,盡量吧過濾性好的字段放在前邊锰茉,例如:手機號姓名部門呢蔫,這樣每一個字段的篩選會過濾掉更多,使得后面的查詢更輕松

具體是全部失效還是失效一般需驗證----------------------------------------

2. order by

order by 使用索引的原則與 where 之后大部分相同飒筑,排序分為 using filesorts(文件內(nèi)排序)和 using index(索引排序)片吊,對它的優(yōu)化主要目標(biāo)就是消除 using filesorts,使用 using index协屡。

  1. 最佳左前綴原則
  2. 沒有過濾條件的 order by俏脊,是用不到索引的,會產(chǎn)生 using filesort肤晓。也就是要有 where 過濾條件爷贫,或者加 limit。
  3. 多個字段排序順序不同(同時存在asc补憾,desc)漫萄,也會產(chǎn)生 filesort
    其中,最左前綴原則舉例:
    創(chuàng)建了索引 idx_a_b_c余蟹,
order b,c #不滿足最前綴原則
where a='1' order by b,c #a是常量卷胯,不需排序,所以這個滿足左前綴原則
where a like 'a%' order by b,c #同上
order c,a,b #不滿足最前綴原則
order a asc威酒,b desc #不能使用索引窑睁,必須同升同降
order by 與索引

但有時 using filesort 是不可避免的,而 filesort 又分為雙路排序(mysql 4.1之前)和單路排序:

雙路排序:要掃描兩次磁盤得到最終數(shù)據(jù)葵孤,先讀鹊Eァ(第一次)行指針和 order by 列到 buffer,并進行排序尤仍,按照排序后的虛擬列表重新從實體表中獲润锝颉(第二次)數(shù)據(jù),需要兩次 IO,所以誕生了單路排序

單路排序:掃描一次得到數(shù)據(jù)苏遥,直接把所有查找列都讀取出來饼拍,并在 buffer 中排序,然后將 buffer 中排序好的結(jié)果輸出田炭,只需要一次 IO

從上面可以看出师抄,通常情況下,單路排序是要由于雙路排序的教硫,但仍存在特殊情況:取出數(shù)據(jù)太大叨吮,buffer 中存不下,單路排序只能每次取出 buffer 的大小的數(shù)據(jù)(創(chuàng)建 tmp 文件瞬矩,多路合并)茶鉴,如此多次操作,完成全部數(shù)據(jù)的查找景用,導(dǎo)致多次 IO涵叮,效果可能比雙路排序更糟。伞插。围肥。

解決辦法就是調(diào)整 my.cnf 配置文件中一下兩個參數(shù):

sort_buffer_size,
max_length_for_sort_data

另外,需要什么字段就取蜂怎,不要用 select *,避免查詢結(jié)果因多余字段而過大置尔,超過buffer 大小就不好了杠步。

3. group by

group by 適用于分組,實際上是先排序榜轿,然后才分組幽歼。所以上面的 order by 的原則同樣適用于 group by。如果 group by 使用不當(dāng)谬盐,不僅會產(chǎn)生 using filesort甸私,還會有 using temporary。

除了上面的幾點飞傀,能用 where 就不要用 having皇型。

select * 的危害

1. 影響覆蓋索引
例如:有一個索引 idx_a_b_c, select a,b,c 或者 select a,b 都可以形成覆蓋索引,因為查詢字段小于等于索引的字段才能形成砸烦,一旦多于索引字段弃鸦,就會無效。select * 卻很有可能是查詢字段多于索引字段
2. 排序生成臨時表
由于 mysql 4.1 之后使用的都是單路排序(一次查詢所有查詢列到 buffer 中排序)幢痘,由于 buffer 有限唬格,一旦數(shù)據(jù)超出 buffer,就需要將數(shù)據(jù)分批存儲到新創(chuàng)建的多個臨時表中,全部查詢购岗、排序完成要進行整合汰聋,最后刪除臨時表。這一過程極其耗時喊积,select * 增加了 buffer 爆滿的風(fēng)險烹困。

msyql 優(yōu)化器

mysql優(yōu)化器,可以在查詢時對sql進行優(yōu)化注服,達(dá)到更好的查詢效果韭邓,例如 idx_a_b_c, where 中的順序是 a, c, b,這樣 sql 優(yōu)化器會對其進行優(yōu)化成 a溶弟,b女淑,c使索引得到應(yīng)用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辜御,一起剝皮案震驚了整個濱河市鸭你,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌擒权,老刑警劉巖袱巨,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異碳抄,居然都是意外死亡愉老,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門剖效,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫉入,“玉大人,你說我怎么就攤上這事璧尸≈淞郑” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵爷光,是天一觀的道長垫竞。 經(jīng)常有香客問我,道長蛀序,這世上最難降的妖魔是什么欢瞪? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮徐裸,結(jié)果婚禮上引有,老公的妹妹穿的比我還像新娘。我一直安慰自己倦逐,他們只是感情好譬正,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布宫补。 她就那樣靜靜地躺著,像睡著了一般曾我。 火紅的嫁衣襯著肌膚如雪粉怕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天抒巢,我揣著相機與錄音贫贝,去河邊找鬼。 笑死蛉谜,一個胖子當(dāng)著我的面吹牛稚晚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播型诚,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼客燕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了狰贯?” 一聲冷哼從身側(cè)響起也搓,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涵紊,沒想到半個月后傍妒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡摸柄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年颤练,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驱负。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡昔案,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出电媳,到底是詐尸還是另有隱情,我是刑警寧澤庆亡,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布匾乓,位于F島的核電站,受9級特大地震影響又谋,放射性物質(zhì)發(fā)生泄漏拼缝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一彰亥、第九天 我趴在偏房一處隱蔽的房頂上張望咧七。 院中可真熱鬧,春花似錦任斋、人聲如沸继阻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘟檩。三九已至抹缕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間墨辛,已是汗流浹背卓研。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留睹簇,地道東北人奏赘。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像太惠,于是被迫代替她去往敵國和親磨淌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容