初識MySQL索引

維基百科對數據庫索引的解釋:一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。html

MySQL官方解釋:索引(Index)是幫助MySQL高效獲取數據的數據結構。mysql

綜上所述,就能夠獲得索引的本質:索引(在MYSQL中也叫作鍵)是數據結構。算法

對於咱們平常使用的MySQL數據庫來講,它支持多種索引類型,如BTree索引,哈希索引,全文索引等等。然而我在大部分時候都會使用BTree索引,至於哈希索引和全文索引本文暫不討論。sql

索引目的

索引的目的在於提升查詢效率,能夠類比字典,若是要查「mysql」這個單詞,咱們確定須要定位到m字母,而後從下往下找到y字母,再找到剩下的sql。若是沒有索引,那麼你可能須要把全部單詞看一遍才能找到你想要的,若是我想找到m開頭的單詞呢?或者x開頭的單詞呢?是否是以爲若是沒有索引,這個事情根本沒法完成?數據庫

索引原理

最簡單的例子就是若是1000條數據,1到100分紅第一段,101到200分紅第二段,201到300分紅第三段……這樣查第250條數據,只要找第三段就能夠了,一會兒去除了90%的無效數據。但若是是1千萬的記錄呢,分紅幾段比較好?稍有算法基礎的同窗會想到搜索樹,其平均複雜度是lgN,具備不錯的查詢性能。可是考慮到磁盤IO是很是高昂的操做,計算機操做系統作了一些優化,當一次IO時,不光把當前磁盤地址的數據,而是把相鄰的數據也都讀取到內存緩衝區內,由於局部預讀性原理告訴咱們,當計算機訪問一個地址的數據的時候,與其相鄰的數據也會很快被訪問到。每一次IO讀取的數據咱們稱之爲一頁(page)。具體一頁有多大數據跟操做系統有關,通常爲4k或8k,也就是咱們讀取一頁內的數據時候,實際上才發生了一次IO,因此爲了提升性能,每次又能夠把部分數據讀入內存來計算,由於咱們知道訪問磁盤的成本大概是訪問內存的十萬倍左右,這個理論對於索引的數據結構設計很是有幫助。數據結構

咱們如今總結一下,咱們須要這種數據結構可以作些什麼,那就是:每次查找數據時把磁盤IO次數控制在一個很小的數量級,最好是常數數量級。那麼咱們就想到若是一個高度可控的多路搜索樹是否能知足需求呢?就這樣,b+樹應運而生。函數

維基百科:B+ 樹是一種樹數據結構,一般用於數據庫操做系統文件系統中。B+ 樹的特色是可以保持數據穩定有序,其插入與修改擁有較穩定的對數時間複雜度。B+ 樹元素自底向上插入,這與二叉樹剛好相反。性能

詳解b+樹

如上圖,是一顆b+樹,淺藍色的塊咱們稱之爲一個磁盤塊,能夠看到每一個磁盤塊包含幾個數據項(深藍色所示)和指針(黃色所示),如磁盤塊1包含數據項17和35,包含指針P一、P二、P3,P1表示小於17的磁盤塊,P2表示在17和35之間的磁盤塊,P3表示大於35的磁盤塊。真實的數據存在於葉子節點即三、五、九、十、1三、1五、2八、2九、3六、60、7五、7九、90、99。非葉子節點只不存儲真實的數據,只存儲指引搜索方向的數據項,如1七、35並不真實存在於數據表中。大數據

b+樹的查找過程

如上圖所示,若是要查找數據項29,那麼首先會把磁盤塊1由磁盤加載到內存,此時發生一次IO,在內存中用二分查找肯定29在17和35之間,鎖定磁盤塊1的P2指針,內存時間由於很是短(相比磁盤的IO)能夠忽略不計,經過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內存,發生第二次IO,29在26和30之間,鎖定磁盤塊3的P2指針,經過指針加載磁盤塊8到內存,發生第三次IO,同時內存中作二分查找找到29,結束查詢,總計三次IO。真實的狀況是,3層的b+樹能夠表示上百萬的數據,若是上百萬的數據查找只須要三次IO,性能提升將是巨大的,若是沒有索引,每一個數據項都要發生一次IO,那麼總共須要百萬次的IO,顯然成本很是很是高。優化

索引的弊端

索引的優勢咱們都知道就是爲了提升查詢效率,當時他也有本身的缺點。

當一個數據表的字段加了索引以後,加快了檢索速度,可是他同時頁下降了索引列的插入,更新,刪除操做的速度,由於一個行不只是寫入一個數據行,還要更改索引,表的索引越多,須要作的更改就越多,平均性能也就越低。

索引也會佔用磁盤空間,大量的對錶中字段加索引,有可能致使索引文件比數據文件更快的到達表的大小極限。

說白了這就是一種以空間換時間的作法,因此不要建立沒有必要的索引。

建索引的幾大原則

1.用於搜索,排序,或者分組的列建立索引,而對於輸出現實的列則不用於建立索引,也就是說,最佳索引候選列九十出如今where條件後面的列,鏈接子句後面的列,order by,group by後面的列。

2.認真考慮數據列基數,列的基數(carddinality)是指它所容納全部非重複的數值的個數,區分度的公式是count(distinct col)/count(*),比例越大咱們掃描的記錄數越少,惟一鍵的區分度是1,例如,某個列包含1,3,5,3,7,8,7,1,8,他的基數就是5,因此列的基數越高,也就是重複值越少,索引的使用效果越好。

3.索引短小值,例如當數據類型使用int就能存下你須要存儲的數據時,就不要使用bigint。

(1)短小值可讓比較操做更快,從而加快索引檢索速度

(2)短小值可讓索引更短更小,從而減小IO請求

(3)短小值可讓磁盤往內存里加載更多的鍵值,那麼就能夠減小從磁盤讀取數據而更多的直接從內存中讀取

4.最左前綴匹配原則,很是重要的原則,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的順序能夠任意調整,好比like (%as)就不走索引,而like(as%)就能夠。

5.索引列不能參與計算,保持列「乾淨」,好比from_unixtime(create_time) = ’2019-12-16’就不能使用到索引,緣由很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,須要把全部元素都應用函數才能比較,顯然成本太大。因此語句應該寫成create_time = unix_timestamp(’2014-05-29’),因此咱們知道了mysql中內置函數是不走索引的。

6.儘可能的擴展索引,不要新建索引,好比表中已經有a的索引,如今要加(a,b)的索引,那麼只須要修改原來的索引便可。

查詢優化神器 - explain命令

關於explain命令相信你們並不陌生,具體用法和字段含義能夠參考官網explain-output

參考資料:

MySQL技術內幕-第5版

美團技術團隊-MySQL索引原理及慢查詢優化

相關文章
相關標籤/搜索