在大概瞭解了MySQL 各類類型的索引,以及索引自己的利弊與判斷一個字段是否需要建立索引以後,就要着手建立索引來優化Query 了。在不少時候,WHERE 子句中的過濾條件並不僅是針對於單一的某個字段,常常會有多個字段一塊兒做爲查詢過濾條件存在於 WHERE 子句中。在這種時候,就必需要判斷是該僅僅爲過濾性最好的字段創建索引,仍是該在全部字段(過濾條件中的)上創建一個組合索引。併發
對於這種問題,很難有一個絕對的定論,需要從多方面來分析考慮,平衡兩種方案各自的優劣,而後選擇一種最佳的方案。由於從上一節中已瞭解到索引在提 高某些查詢的性能同時,也會讓某些更新的效率降低。而組合索引中由於有多個字段存在,理論上被更新的可能性確定比單鍵索引要大不少,這樣帶來的附加成本也 就比單鍵索引要高。可是,當WHERE 子句中的查詢條件含有多個字段時,經過這多個字段共同組成的組合索引的查詢效率確定比只用過濾條件中的某一個字段建立的索引要高。由於經過單鍵索引過濾的 數據並不完整,和組合索引相比,存儲引擎需要訪問更多的記錄數,天然就會訪問更多的數據量,也就是說須要更高的 IO 成本。性能
可能有朋友會說,那能夠建立多個單鍵索引啊。確實能夠將 WHERE 子句中的每個字段都建立一個單鍵索引。可是這樣真的有效嗎?在這樣的狀況下,MySQL Query Optimizer 大多數時候都只會選擇其中的一個索引,而後放棄其餘的索引。即便他選擇了同時利用兩個或更多的索引經過 INDEX_MERGE 來優化查詢,所收到的效果可能並不會比選擇其中某一個單鍵索引更高效。由於若是選擇經過 INDEX_MERGE 來優化查詢,就需要訪問多個索引,同時還要將幾個索引進行 merge 操做,這帶來的成本可能反而會比選擇其中一個最有效的索引更高。優化
在通常的應用場景中,只要不是其中某個過濾字段在大多數場景下能過濾90%以上的數據,而其餘的過濾字段會頻繁的更新,通常更傾向於建立組合索引, 尤爲是在併發量較高的場景下。由於當併發量較高的時候,即便只爲每一個Query節省了不多的 IO 消耗,但由於執行量很是大,所節省的資源總量仍然是很是可觀的。索引
固然,建立組合索引並非說就需要將查詢條件中的全部字段都放在一個索引中,還應該儘可能讓一個索引被多個 Query 語句利用,儘可能減小同一個表上的索引數量,減小由於數據更新帶來的索引更新成本,同時還能夠減小由於索引所消耗的存儲空間。資源
此外,MySQL 還提供了另一個優化索引的功能,那就是前綴索引。在 MySQL 中,能夠僅僅使用某個字段的前面部份內容作爲索引鍵索引該字段,以達到減少索引佔用的存儲空間和提升索引訪問效率的目的。固然,前綴索引的功能僅僅適用於 字段前綴隨機重複性很小的字段。若是需要索引的字段前綴內容有較多的重複,索引的過濾性天然也會隨之下降,經過索引所訪問的數據量就會增長,這時候前綴索 引雖然可以減小存儲空間消耗,可是可能會形成 Query 訪問效率的極大下降,得不償失。
class