淺談MySQL的索引(3)


上一篇我們從索引的應(yīng)用層次分析,說到了普通索引、唯一索引、主鍵索引、復(fù)合索引。這一期,我們在從其他層次學(xué)習(xí)洗索引。


一、前期回顧

  • 從索引存儲結(jié)構(gòu)劃分:B?Tree索引、Hash索引、FULLTEXT全文索引以及R?Tree索引

  • 從應(yīng)用層次劃分:普通索引、唯一索引、主鍵索引、復(fù)合索引

  • 從鍵值劃分:主鍵索引、輔助索引(二級索引)

  • 從數(shù)據(jù)存儲以及索引邏輯關(guān)系劃分:聚集索引、非聚集索引


二、索引的分類


再說?輔助索引?之前,我們先了解什么是聚集索引、非聚集索引;


聚簇索引和非聚簇索引:B+Tree的葉子節(jié)點存放主鍵索引值和行記錄就屬于聚簇索引;如果索引值和行?記錄分開存放就屬于非聚簇索引


在MyIsam中,主索引和輔助索引在結(jié)構(gòu)上沒有任何區(qū)別,只是主索引要求key是唯一的,而輔助索引的key是可以重復(fù)的。

MyIsam中的主鍵索引如上圖,輔助索引如下圖:

在InnoDB中要求表必須有主鍵(MyIsam可以沒有),如果沒有顯示指定,則MySQL系統(tǒng)會自動選擇一個可以唯一標(biāo)識數(shù)據(jù)記錄的列作為主鍵,如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含字段作為主鍵類型為長整形

上圖是?InnoDB?主索引(同時也是數(shù)據(jù)文件)的示意圖,可以看到葉節(jié)點包含了完整的數(shù)據(jù)記錄,這種索引叫做聚集索引。因為?InnoDB?的數(shù)據(jù)文件本身要按主鍵聚集。

nnoDB?的輔助索引?data?域存儲相應(yīng)記錄主鍵的值而不是地址。換句話說,InnoDB?的所有輔助索引都引用主鍵作為?data?域。

聚集索引這種實現(xiàn)方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄,即回表查詢。


三、索引優(yōu)化時應(yīng)注意的問題

????前面我們說了很多索引的定義以及結(jié)構(gòu),接下來我們聊一聊索引優(yōu)化時應(yīng)該注意的問題。

索引分析我們就不得不借助explain命令了。explain是我們優(yōu)化sql語句中常用的命令,它可以輸出select執(zhí)行的詳細(xì)信息。

  • select_type:查詢類型

    • SIMPLE?:表示查詢語句不包含子查詢或union

    • PRIMARY:表示此查詢是最外層的查詢

    • UNION:表示此查詢是UNION的第二個或后續(xù)的查詢

    • DEPENDENT?UNION:UNION中的第二個或后續(xù)的查詢語句,使用了外面查詢結(jié)果

    • UNION?RESULT:UNION的結(jié)果

    • SUBQUERY:SELECT子查詢語句

    • DEPENDENT?SUBQUERY:SELECT子查詢語句依賴外層查詢的結(jié)果。

  • type:表示存儲引擎查詢數(shù)據(jù)時采用的方式,通過它可以判斷查詢是全表掃描還是基于索引的部分掃描

    • ALL:表示全表掃描,性能最差

    • index:表示基于索引的全表掃描,先掃描索引再掃描全表數(shù)據(jù)

    • range:表示使用索引范圍查詢。使用>、>=、<、<=、in等等

    • ref:表示使用非唯一索引進(jìn)行單值查詢

    • eq_ref:一般情況下出現(xiàn)在多表join查詢,表示前面表的每一個記錄,都只能匹配后面表的一?行結(jié)果

    • const:表示使用主鍵或唯一索引做等值查詢,常量查詢。

    • NULL:表示不用訪問表,速度最快

  • possible_keys:表示查詢時能夠使用到的索引。注意并不一定會真正使用,顯示的是索引名稱

  • key:表示查詢時真正使用到的索引,顯示的是索引名稱

  • rows:MySQL查詢優(yōu)化器會根據(jù)統(tǒng)計信息,估算SQL要查詢到結(jié)果需要掃描多少行記錄

  • key_len:表示查詢使用了索引的字節(jié)數(shù)量。可以判斷是否全部使用了組合索引

  • Extra:表示很多額外的信息,各種操作會在Extra提示相關(guān)信息

    • Using?where:表示查詢需要通過索引回表查詢數(shù)據(jù)。

    • Using?index:表示查詢需要通過索引,索引就可以滿足所需數(shù)據(jù)。

    • Using?filesort:表示查詢出來的結(jié)果需要額外排序,數(shù)據(jù)量小在內(nèi)存,大的話在磁盤,因此有Using?filesort?建議優(yōu)化

    • Using?temprorary:查詢使用到了臨時表,一般出現(xiàn)于去重、分組等操作


?

????對于查詢占主要的應(yīng)用來說,索引顯得尤為重要。很多時候性能問題很簡單的就是因為我們發(fā)忘了添加索引而造成的,或者說沒有添加更為有效的索引導(dǎo)致。如果不加索引的話,那么查詢?nèi)魏文呐轮皇且粭l特定的數(shù)據(jù)都會進(jìn)行一次全表掃描,如果一張表的數(shù)據(jù)量很大而符合條件的結(jié)果又很少,那么不加索引會引起致命的性能下降。但是也不是什么情況下非要加索引不可,比如性別可能就只有兩個值,建索引不僅沒有優(yōu)勢,還會影響到更新速度,這被稱為過度索引。

?

????復(fù)合索引使用時遵循最左前綴原則,最左前綴顧名思義,就是最左優(yōu)先,即查詢中使用到最左邊的列,?那么查詢就會使用到索引,如果從索引的第二列開始查找,索引將失效

????3.2、LIKE查詢????

????MySQL在使用Like模糊查詢時,索引是可以被使用的,只有把%字符寫在后面才會使用到索引

?

????對MySQL來說,NULL是一個特殊的值,從概念上講,NULL意味著“一個未知值”,它的處理方式與其他?值有些不同。比如:不能使用=,<,>這樣的運算符,對NULL做算術(shù)運算的結(jié)果都是NULL,count時?不會包括NULL行等,NULL比空字符串需要更多的存儲空間等

????雖然MySQL可以在含有NULL的列上使用索引,但NULL和其他數(shù)據(jù)還是有區(qū)別的,不建議列上允許為?NULL。最好設(shè)置NOT?NULL,并給一個默認(rèn)值,比如0和?‘’?空字符串等,如果是datetime類型,也可以?設(shè)置系統(tǒng)當(dāng)前時間或某個固定的特殊值,例如'1970-01-01?00:00:00'。

?

????MySQL查詢支持filesort和index兩種方式的排序,filesort是先把結(jié)果查出,然后在緩存或磁盤進(jìn)行排序?操作,效率較低。使用index是指利用索引自動實現(xiàn)排序,不需另做排序操作,效率會比較高

????3.5、不要在列上進(jìn)行運算

select?*?from?user?where?YEAR(adddate)

????3.6、不適用NOT?IN

NOT?IN?和操作都不會使用索引將進(jìn)行全表掃描,NOT?IN可以NOT?EXISTS代替,

????3.7、主鍵的設(shè)計????

當(dāng)我們設(shè)計表時,如果使用的是InnodDB,主鍵盡可能選擇有序自增的值,這樣在出入數(shù)據(jù)時可以減少BTree的分裂調(diào)整,如果不是有序自增的,可能會造成BTree頻繁的分裂調(diào)整。

????3.8、分頁查詢優(yōu)化

  • 問題:偏移量固定時,返回記錄增多

    • 在查詢記錄時,返回記錄量低于100條,查詢時間基本沒有變化,差距不大。隨著查詢記錄?量越大,所花費的時間也會越來越多

  • 問題:返回記錄增多,偏移量變大

    • 在查詢記錄時,如果查詢記錄量相同,偏移量超過100后就開始隨著偏移量增大,查詢時間?急劇的增加。(這種分頁查詢機制,每次都會從數(shù)據(jù)庫第一條記錄開始掃描,越往后查詢越慢,而?且查詢的數(shù)據(jù)越多,也會拖慢總查詢速度。)

優(yōu)化??:??1、先利用覆蓋索引


select?id?from?`user`?limit?10000,100;

2、再利用子查詢優(yōu)化

select?*?from?`user`?where?id>=?(select?id?from?user?limit?10000,1)?limit?100;


原因:使用了id做主鍵比較(id>=),并且子查詢使用了覆蓋索引進(jìn)行優(yōu)化



好了關(guān)于索引暫時就說這些,

…………………………………分割線……………………………

不積跬步,無以至千里;不積小流,無以成江海。

關(guān)注我,每天分享一些小知識點。分享自己的小心得,包含但不限于初、中、高級面試題呦!!!


我都墨跡這么半天了?,你不點關(guān)注,不點贊,不收藏,還不轉(zhuǎn)發(fā),你想干啥!!!


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容