MySQL中的索引——概念篇

使用索引的目的

使用索引的目的是提高數(shù)據(jù)庫查詢的效率。索引是怎么提高數(shù)據(jù)庫查詢的效率的呢?舉個通俗的例子,查字典。數(shù)據(jù)庫中的數(shù)據(jù)就好比新華字典中的詞條,索引就是新華字典的目錄。沒有建立索引的數(shù)據(jù)庫就好像被撕掉目錄的新華字典,只能從頭到尾一條一條地查詢,效率極其低下。

為了能更快地查字典,哦不,是查詢數(shù)據(jù)庫,我們就需要為數(shù)據(jù)庫建立索引。

索引的原理

索引的主要思想是將數(shù)據(jù)分段,從而減少查詢時的無效數(shù)據(jù),提高查詢效率。比如有1000條數(shù)據(jù),1到100分成第一段,101到200分成第二段,201到300分成第三段……這樣查第250條數(shù)據(jù),只要找第三段就可以了,一下子去除了90%的無效數(shù)據(jù)。

當然,上面只是主要思想,MySQL使用了更加具體的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)索引。本文不對索引的數(shù)據(jù)結(jié)構(gòu)展開討論。

建立索引的幾大原則

如何建立合適的索引,從而最大程度地優(yōu)化查詢效率是一件需要精心設(shè)計的事情。本節(jié)只介紹幾個建立索引時須遵循的原則。

  1. 最左前綴匹配原則,非常重要的原則。mysql會一直向右匹配直到遇到范圍查詢>、<、between、like就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調(diào)整。關(guān)于最左前綴匹配原則,在最左前綴匹配原則一節(jié)有詳細說明。
  2. 盡量選擇區(qū)分度高的列作為索引,區(qū)分度公式為count(distinct col)/count(*),即一列中內(nèi)容不同的記錄數(shù)占總記錄數(shù)的比例。通過這個公式我們可以得到字段不重復的比例,比例越大我們掃描的記錄數(shù)越少,唯一鍵的區(qū)分度是1,而一些狀態(tài)、性別字段可能在大數(shù)據(jù)面前區(qū)分度就是0。所以唯一索引的效率是最高的。在不是唯一鍵的時候,就要具體情況具體分析了,這也是索引設(shè)計的關(guān)鍵點之一。
  3. 索引列不能參與計算,保持列“干凈”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡單,索引的數(shù)據(jù)結(jié)構(gòu)中存的都是數(shù)據(jù)表中的字段值,但進行檢索時,需要把所有元素都應用函數(shù)才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’);
  4. 盡量的擴展索引,不要新建索引。比如表中已經(jīng)有a的索引,現(xiàn)在要加(a,b)的索引,那么只需要修改原來的索引即可
  5. 使用短索引。如果對串列進行索引,應該指定一個前綴長度,只要有可能就應該這樣做 。
    例如,如果有一個 CHAR(200) 列,如果在前 10 個或 20 個字符內(nèi),多數(shù)值是惟一的,
    那么就不要對整個列進行索引。對前 10 個或 20 個字符進行索引能夠節(jié)省大量索引空
    間,也可能會使查詢更快。

最左前綴匹配原則

最左前綴使用場景是使用復合索引的時候。當使用復合索引時,如果想要索引有效,where之后的表達式就要滿足最左前綴匹配原則。

我總結(jié)了一下最左前綴匹配的特點,就是從表達式最左邊開始,到第一個范圍查詢結(jié)束,在這個閉區(qū)間內(nèi)的字段應該是索引字段的最左前綴。

最左前綴

在這里解釋一下最左前綴,因為沒有百度到感覺比較靠譜的解釋,所以我在這里談一下我的理解,僅供參考。

前綴應該不用解釋了,學過英語的都該懂點。前綴加個就是左前綴了,表示從左邊開始查找的前綴。但是,這個左只是表示查找的順序是從左邊開始,不是從右邊開始,并沒有說從哪一位開始,可能是第一位,也可能是第三位。這時候再加一個 就表示了從最左邊開始。

比如復合索引是(a,b,d,c),那么查詢時表達式的字段順序為(a)、(a,b)、(a,b,d)、(a,b,d,c)的這些都是它的最左前綴,而(b)、(a,d)、(a,b,c)、(a,b,c,d)這些就不是。

關(guān)于MySQL的查詢優(yōu)化器

最左前綴的概念我們已經(jīng)明白了,但是在MySQL中的情況又有點不同。比如我們發(fā)現(xiàn),索引的順序是(a,b,d,c),我們的查詢條件是這樣寫的:where b=10 and c=16 and a=26 and d=0,從嚴格意義上來講,這個順序是不符合最左前綴匹配原則的,但是MySQL的確使用索引完成了查詢。這是怎么回事呢?這是因為MySQL的查詢優(yōu)化器幫我們調(diào)整了查詢條件的順序。MySQL查詢優(yōu)化器會判斷糾正一條sql語句該以什么樣的順序執(zhí)行效率最高,最后才生成真正的執(zhí)行計劃。在有索引的情況下當然是利用索引查詢順序的效率最高咯,所以,MySQL查詢優(yōu)化器會最終以索引的順序進行查詢執(zhí)行。

最左前綴匹配原則的原理

上面說了這么多的最左前綴的概念,那么我們到底為什么一定要符合最左前綴匹配原則呢?

因為復合索引只有第一個字段是絕對有序的,從第二個開始的字段都只是相對前一個字段有序,在全局范圍內(nèi)是無序的。只有滿足最左前綴原則,才可以保證查詢內(nèi)容的有序,而有序又是索引使用的前提。

我們來看個例子,以該表的(name,cid)復合索引為例,它內(nèi)部結(jié)構(gòu)簡單說就是下面這樣排列的:

name cid
a 6
c 4
c 5
h 1
z 9

MySQL創(chuàng)建復合索引的規(guī)則是首先會對復合索引的最左邊的,也就是第一個name字段的數(shù)據(jù)進行排序,在第一個字段的排序基礎(chǔ)上,然后再對后面第二個的cid字段進行排序。其實就相當于實現(xiàn)了類似 order by name cid這樣一種排序規(guī)則。

第一個name字段是絕對有序的,而第二字段就是無序的了。所以通常情況下,直接使用第二個cid字段進行條件判斷是用不到索引的。

那么什么時候才能用到呢?當然是cid字段的索引數(shù)據(jù)也是有序的情況下才能使用咯,什么時候才是有序的呢?觀察可知,當然是在name字段是等值匹配的情況下,cid才是有序的。發(fā)現(xiàn)沒有,觀察兩個name名字為 ccid字段是不是有序的呢。從上往下分別是4 5。這也就是MySQL索引規(guī)則中要求復合索引要想使用第二個索引,必須先使用第一個索引的原因(最左前綴匹配原則)。

補充使用索引時的具體情況

更多使用索引的詳細情況,可以參考最左前綴原理與相關(guān)優(yōu)化

本文的參考資料

http://blog.jobbole.com/86594/

https://www.zhihu.com/question/36996520/answer/93256153

http://www.kancloud.cn/kancloud/theory-of-mysql-index/41857

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容