????上一篇我們從索引的存儲結構分析,說到了B Tree索引、Hash索引、FULLTEXT全文索引。這一期,我們在從其他層次學習洗索引。
一、前期回顧:
從索引存儲結構劃分:B Tree索引、Hash索引、FULLTEXT全文索引以及R Tree索引
從應用層次劃分:普通索引、唯一索引、主鍵索引、復合索引
從鍵值劃分:主鍵、輔助
從數據存儲以及索引邏輯關系劃分:聚集索引、非聚集索引
二、索引的分類
2.1、普通索引
????????普通索引既我們平時常用的索引,默認使用的是BTree。
ALTER?TABLE?`user`ADD?INDEX?`index_userNm`?(`username`)?USING?BTREE?COMMENT?'用戶名索引';--?或者ALTER?TABLE?`user`ADD?INDEX?`index_userNm`?(`username`);
2.2、唯一索引
????????與普通索引類似,不同的點在于:索引的值必須唯一,允許有空值。換句話說?某種程度上說的就是表中索引鎖標記的唯一列。
ALTER?TABLE?`user`?ADD?UNIQUE?INDEX?`index_un_id`(`id`);
主鍵索引
????????與唯一索引的區別就是索引標記的列不允許有空值,換句話說就是主鍵列上加的索引。
ALTER?TABLE?`user`?ADD?PRIMARY?KEY?(`id`);
2.3、復合索引
????????又名聯合索引,也是我們比較常用的索引類型之一。在數據表的2列或>2列共同組成的索引。而上面我們說的普通索引、唯一索引、主鍵索引又叫單一索引。顧名思義是指索引列只有一列,而用戶可以在多個列上建立索引,這種索引就叫復合索引,也叫組合索引、聯合索引,復合索引可以代替多個單一索引,相遇多個單一索引,復合索引所需的開銷更小。
在這里復合索引還有個小小的區分:窄索引、寬索引
窄索引:指索引列為1-2列的索引
寬索引:指索引列超過2列的索引
??索引設計原則:能用窄索引不用寬索引,因為窄索引往往比組合索引更有效
? ?值得我們重點關注的是:
需要加索引的字段,要在where條件中。
數據量少的字段不需要加索引。最窄的字段放在鍵的左邊。
如果where條件中是OR關系,必須所有的or條件都必須是獨立索引,否則加索引不起作用。見:mysql關于or的索引問題
最左匹配原則。
只要列中包含有NULL值都將不會被包含在索引中,復合索引中只要有一列含有NULL值,那么這一列對于此復合索引就是無效的。所以我們在數據庫設計時不要讓字段的默認值為NULL。
eg:
假設某個表有一個聯合索引(c1,c2,c3,c4)以下選項哪些字段使用了該索引:
A where c1=x and c2=x and c4>x and c3=x
B where c1=x and c2=x and c4=x order by c3
C where c1=x and c4= x group by c3,c2
D where c1=? and c5=? order by c2,c3
E where c1=? and c2=? and c5=? order by c2,c3
接下來借用上面的例子,我們求證一下:
首先創建表:
CREATE?TABLE?t(??c1?CHAR(1)?not?null,??c2?CHAR(1)?not?null,??c3?CHAR(1)?not?null,??c4?CHAR(1)?not?null,??c5?CHAR(1)?not?null)ENGINE?myisam?CHARSET?UTF8;
創建索引:
alter?table?t?add?index?c1234(c1,c2,c3,c4);
隨機搞兩條數據:
insert?into?t?VALUES('1','1','1','1','1'),('2','2','2','2','2')
使用MySql Explain開始分析題目結果:
A 選項:where c1=x and c2=x and c4>x and c3=x
說明下:UTF-8 編碼,一個索引的長度為3,如上圖我們可以看到,c1,c2,c3,c4均使用到了該索引。
但是如果我們將查詢條件調整下或者去掉一個,索引又是怎么使用的呢:
由上面4個圖可以看出,我們分別調整了各個列的位置,使用>和使用>的位置,發現索引都是正常使用的,所以可以得出:
使用“<” / “>”并不影響索引的選擇
where條件和創建索引的列保持一致時,條件的位置(順序)并不影響索引的選擇。
但是,如果我們對A組where條件做些調整呢?
當我們刪除分別其中一個條件c1、c2、c3后,發現使用索引的個數也發生了變化。得出結論:
當使用復合索引時,沒有使用第一個復合索引,不觸發索引的使用
使用復核索引時,索引的選擇與where的條件順序和索引建立時的順序是否一致存在關系,當順序中斷時,后續的索引列將不被選擇。
如果我們對A組where條件做些調整呢?
當我們使用or,或者like時,通過上面4張圖可以清醒的得出:
當使用or時,不會使用索引
當條件順序與索引創建順序一致,且使用?“like”?/?“like%”時,索引可以正常被選中
當條件順序與索引創建順序一致,且使用 “%like%”,索引無法被選中
當條件順序與索引創建順序不一致時,且第一個條件不是索引創建時的首列,則無法選中索引
B選項:where c1=x and c2=x and c4=x order by c3
通過上圖可以發現,key_len長度說明c1,c2字段用到了該索引,Extra顯示并沒有使用臨時表進行排序,說明排序是使用了索引的,但并沒有計算在key_len值中,也沒有起到連接c4的作用,說明索引到c3這里是斷掉的。
排序其實是利用聯合索引直接完成了的,即:使用了c1234聯合索引,就已經使得c1下c2,c2下c3,c3下c4是有序的了,所以實際是排序利用了索引,c3字段并沒有使用該索引。
C選項:where c1=x and c4= x group by c3,c2
通過上面兩圖,能看出使用group by 一般先生成臨時文件,再進行排序,但是字段順序為c2,c3時,并沒有用臨時表進行排序,而是利用索引排序好的;當group by字段為c3,c2時,由于與索引字段順序不一致,所以分組和排序并沒有利用到索引。
D選項:where c1=? and c5=? order by c2,c3
通過此圖可以看出 order by 和group by 類似,字段順序與索引一致時,會使用索引排序;字段順序與索引不一致時,不使用索引。
E選項:where c1=? and c2=? and c5=? order by c2,c3
其實選項E的結果分析在上述ABCD的結果中都分析過了,這里只有c1,c2字段使用了該索引。
綜上所述問題答案:
????A:四個字段均使用了該索引
????B:c1,c2字段使用了該索引
????C:c1字段使用該索引
????D:c1字段使用該索引
????E:c1,c2字段使用了該索引
三、小結:
索引的最左原則(左前綴原則),如(c1,c2,c3,c4....cN)的聯合索引,
where 條件按照索引建立的字段順序來使用(不代表and條件必須按照順序來寫),
如果中間某列沒有條件,或使用like會導致后面的列不能使用索引。
索引也能用于分組和排序,分組要先排序,在計算平均值等等。所以在分組和排序中,如果字段順序可以按照索引的字段順序,即可利用索引的有序特性。
不知不覺寫到這又有 2.5k 多字了,本期我們就寫到這里,下期我們繼續
探討索引。
…………………………………分割線……………………………
不積跬步,無以至千里;不積小流,無以成江海。
關注我,每天分享一些小知識點。分享自己的小心得,包含但不限于初、中、高級面試題呦!!!
我都墨跡這么半天了 ,你不點關注,不點贊,不收藏,還不轉發,你想干啥!!!