0.預備
假設我們有表 user (id,name)列
1.聯合索引是個什么東西
我們知道,對於表的單列(如id)數據,是可以建立索引的,對於多列(id和name組合,或者,name和id組合),也可以建立索引。聯合索引,也稱之為組合索引。
先來看單列索引的邏輯結構。

由此得出索引的三個特征:索引有序+高度較低+存儲列值
聯合索引也滿足這三個特征,但這里的邏輯圖就不畫了,而是以更直觀的方式來展現其查找邏輯,這里應注意,聯合索引的列有前后,以id列在前、name列在后為例。
建聯合索引前的情況

建聯合索引后的情況(先按ID排序+再按Name排序)

2.建立聯合索引的語法
create index indexName on tableName(column1,column2,...,columnN),如create idx_un_userid_username on user(id,name)
聯合索引可以建立多列(列數大於2)的索引,建議列數最多不要越過3列,超過3列,應重新設計表。
3.聯合索引的好處
A:避免回表
在執行計划中,table access by index rowid代表是回表動作。
如在user的id列建有索引,select id from user這個不用回表,直接從索引中讀取id的值,而select id,name from user中,不能返回除id列其他的值,所以必須要回表。
如果建有了id和name列的聯合索引,則可以避免回表。
另外,建立了id和name的聯合索引(id列在在前),則select id from user可以避免回表,而不用單獨建立id列的單列索引。
B:兩個單列查詢返回行較多,同時查返回行較少,聯合索引更高效。
如果select * from user where id=2 和select * from user where name='tom' 各自返回的行數比較多,而select * from user where id=2 and name='tom'返回的行數比較少,那么這個時候使用聯合索引更加高效。
4.什么時候該用聯合索引以及如何設計組合索引更高效
A:等值查詢中,查詢條件a返回的條目比較多,查詢條件b返回的條目比較多,而同時查詢a、b返回的條目比較少,那么適合建立聯合索引;
B:對於有等值查詢的列和范圍查詢的列,等值查詢的列建在前、范圍查詢的列建在后比較實用;
C:如第3點A中的另外說到,如果聯合索引列的前置列與索引單列一致,那么單列查詢可以用到索引,這樣就避免了再建單列索引,因此聯合索引的前置列應盡量與單列一致;
5.聯合索引在DML時候的性能分析
Insert:索引越多插入明顯慢得多,這是因為記錄必須與索引同時更新,而要維護索引那種有序排列的結構,就必須把新增的索引鍵值插入到特定的位置,而不是隨機排放,這里就涉及到重 組數據的動作,如果索引塊存不下,如果索引塊存不下,則還要涉及到擴展索引塊的動作,這都需要很大的開銷。
相對於有序插入,無序插入時索引的影響更加驚人,因為有序插入時,由於插入的數據有一定的順序,可以在准備工作后快速擴展新塊和批量重組,而對於無序操作,批量則不可能。
Delete:刪除影響所有的索引,在海量數據庫定位刪除少量記錄時,這個條件列是索引列顯然是必要的,但過多的索引還是會影響明顯,因為其他列的索引也要更新。在經常要刪除大量記錄的 時候,危害加劇。另外,delete刪除索引后,索引塊中的相關需要刪除記錄只是被打上了一個刪除標志而已,並沒有真正刪除。
Update:更新的影響最小,如果是更新整條記錄則與delete類似,如果是修改某列時,則不會觸及到其他索引列的維護。
6.使用聯合索引需要注意的地方
A:超過3個列的聯合索引不合適,否則雖然減少了回表動作,但索引塊過多,查詢時就要遍歷更多的索引塊了;
B:建索引動作應謹慎,因為建索引的過程會產生鎖,不是行級鎖,而是鎖住整個表,任何該表的DML操作都將被阻止,在生產環境中的繁忙時段建索引是一件非常危險的事情;
C:對於某段時間內,海量數據表有頻繁的更新,這時可以先刪除索引,插入數據,再重新建立索引來達到高效的目的。
