MySQL多列索引

多列索引(Multiple-Column Indexes)也稱爲複合索引(composite index),也即同時對多個列建立索引。


那麼問題來了,建立多列索引後,例如建立索引(a, b, c),那麼單獨對a或者b或者c進行查詢,會走索引這條路線嗎?

答案是:根據最左前綴原則,也就是對a或者(a,b)或者(a, b, c)查詢會用到索引,但以b或者c來查詢而不加上a則不會走索引,mysql文檔對此有比較完整的例子,可以看一下。說原則是沒錯,但爲什麼是這樣,這就得追溯到如何實現多列索引的問題。


在mysql文檔中並沒有相關說明,但經過一番google之後,有篇博文提到了這個問題,在Quora中也有人提出了類似的問題:對於多列索引,mysql會先按照多列索引定義的順序來連接成一個“新的索引鍵”,然後據此建立一個B+樹,因此,最左前綴原則也得到解釋,當查詢只出現前幾個列來作爲查詢時,可以通過B+樹得到以這個前綴開頭的列,由於B+樹中的值是排序的,因此接下來就是你要的值,問題就得到解決了。但如果沒有以第一個列開頭的話,是無法找到索引入口的。


那麼,問題又來了,當沒有多列索引時,只使用多個單列索引時,這些單列索引是否會起作用?

答案是:具體問題具體分析,在mysql中有種 index merge optimization 技術,暫且翻譯爲索引歸併優化技術吧~ 當索引查詢滿足一定條件的時候(mysql文檔有詳細說明,我這裏就不重複了),mysql是可以利用索引來查詢的,但總體的做法無非就是:先通過這多個列的索引分別得到索引結果,然後再根據相應的索引歸併優化算法進行歸併。從這也不難看出,但這顯然就不是很直接,而且索引歸併優化算法也並不總是像你想的那樣優化(The Optimization That (Often) Isn’t: Index Merge Intersection),因此還是那句話,具體問題具體分析。下面就來具體看個案例,該案例改編自stackoverflow上的提問


假設你現在有張表,簡化爲之後有列userID和postDate,你每次查詢時,需要返回某個具體user的所有發表文章,並且是以發表時間降序方式返回,即最新發表的在前,之前發表的在後,這時由於頻繁地使用排序,自然希望能夠建立個索引提高效率,正如被採納的回答那樣,如果使用多個單列索引,則查詢中並沒有用到postDate的索引,所以之後還需要進行一個排序,而如果採用多列索引,由於B+樹已經是有序的,因此返回的結果已經是有序的,不需要再進行一次排序,所以在這個問題中選擇多列索引爲優,這裏面有個很重要的技巧,用mysql Explain來得到mysql的執行計劃,這種分析方法很值得掌握!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章