1. 程式人生 > 實用技巧 >Python學習————MySQL索引

Python學習————MySQL索引

MySQL索引:

索引原理:

MySQl索引的目的是為了提高資料查詢效率,本質是為了能夠通過不斷地縮小想要獲取的資料範圍
以便篩選出最終想要的資料結果,同時把隨機的事件變成有順序的事件,這樣我們就可以用同一種
方式來鎖定資料。

磁碟IO和預讀:

磁碟讀取資料是靠機械運動,每次讀取資料花費的時間分為 尋道時間,旋轉延遲,傳輸時間三個部分,尋道時
間指的是 磁臂移動到指定磁軌所需要的時間, 旋轉延遲是指磁碟轉速,傳輸時間指的是從磁碟讀出或將資料
寫入磁碟的時間(這個時間基本是零點幾毫秒)
訪問一次磁碟的時間就是一個磁碟IO,當一次IO時,不光把當前磁碟地址的資料,而是把相鄰的資料也都讀取到
記憶體緩衝區內,因為區域性預讀性原理告訴我們,當計算機訪問一個地址的資料時,與其相鄰的資料也會很快被
訪問到,每一次IO讀取的資料我們稱之為一頁,具體一頁的資料量有多少這個和作業系統有關,所以我們在讀取
一頁內的資料的時候,實際上只發生了一次IO

索引的資料結構:

是一顆b+樹,關於b+樹的定義可以參見B+樹,這裡只說一些重點,淺藍色的塊我們稱之為一個

磁碟塊,可以看到每個磁碟塊包含幾個資料項(深藍色所示)和指標(黃色所示),如磁碟塊1

包含資料項17和35,包含指標P1、P2、P3,P1表示小於17的磁碟塊,P2表示在17和35之間的磁碟

塊,P3表示大於35的磁碟塊。真實的資料存在於葉子節點即3、5、9、10、13、15、28、29、36、

60、75、79、90、99。非葉子節點只不儲存真實的資料,只儲存指引搜尋方向的資料項,如17、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,顯然成本非常非常高。

b+樹性質:

1.索引欄位要儘量的小:通過上面的分析,我們知道IO次數取決於b+數的高度h,假設當前資料表的

資料為N,每個磁碟塊的資料項的數量是m,則有h=㏒(m+1)N,當資料量N一定的情況下,m越大,

h越小;而m = 磁碟塊的大小 / 資料項的大小,磁碟塊的大小也就是一個數據頁的大小,是固定的,

如果資料項佔的空間越小,資料項的數量越多,樹的高度越低。這就是為什麼每個資料項,即索引

欄位要儘量的小,比如int佔4位元組,要比bigint8位元組少一半。這也是為什麼b+樹要求把真實的資料

放到葉子節點而不是內層節點,一旦放到內層節點,磁碟塊的資料項會大幅度下降,導致樹增高。

當資料項等於1時將會退化成線性表。

2.索引的最左匹配特性:當b+樹的資料項是複合的資料結構,比如(name,age,sex)的時候,b+數是

按照從左到右的順序來建立搜尋樹的,比如當(張三,20,F)這樣的資料來檢索的時候,b+樹會優先比較

name來確定下一步的所搜方向,如果name相同再依次比較age和sex,最後得到檢索的資料;

但當(20,F)這樣的沒有name的資料來的時候,b+樹就不知道下一步該查哪個節點,因為建立搜尋樹的

時候name就是第一個比較因子,必須要先根據name來搜尋才能知道下一步去哪裡查詢。比如當(張

三,F)這樣的資料來檢索時,b+樹可以用name來指定搜尋方向,但下一個欄位age的缺失,所以只能把

名字等於張三的資料都找到,然後再匹配性別是F的資料了, 這個是非常重要的性質,即索引的最左

匹配特性。

聚集索引和輔助索引:

在資料庫中,B+樹的高度一般在2~4層 ,這也就是說查詢某個鍵值的行記錄時最多需要2~4次IO,

現在的機械硬碟每秒可以做到至少100次的IO,這也就是說著2~4次IO也不過零點幾秒。

在資料苦衷的B+樹索引可以分為聚集索引(clustered index)和輔助索引(secondary index),

聚集索引與輔助索引相同的是:不管是聚集索引還是輔助索引,其內部都是B+樹的形式,及高度是

平衡的,葉子節點存放著所有的資料。

聚集索引與輔助索引不同的是:葉子節點存放的是否是一整行的資訊。

InnoDB儲存引擎表示索引組織表,即表中資料按照主鍵順序存放。而聚集索引(clustered index)就是
按照每張表的主鍵構造一棵B+樹,同時葉子結點存放的即為整張表的行記錄資料,也將聚集索引的葉子結點稱為
資料頁。聚集索引的這個特性決定了索引組織表中資料也是索引的一部分。同B+樹資料結構一樣,每個資料頁都
通過一個雙向連結串列來進行連結。
    
#如果未定義主鍵,MySQL取第一個唯一索引(unique)而且只含非空列(NOT NULL)作為主鍵,InnoDB使
用它作為聚簇索引。
    
#如果沒有這樣的列,InnoDB就自己產生一個這樣的ID值,它有六個位元組,而且是隱藏的,使其作為聚簇索引。

#由於實際的資料頁只能按照一棵B+樹進行排序,因此每張表只能擁有一個聚集索引。在多少情況下,查詢優化
器傾向於採用聚集索引。因為聚集索引能夠在B+樹索引的葉子節點上直接找到資料。此外由於定義了資料的邏輯
順序,聚集索引能夠特別快地訪問針對範圍值得查詢。

聚集索引的好處之一:它對主鍵的排序查詢和範圍查詢速度非常快,葉子節點的資料就是使用者所要查詢的資料。如使用者需要查詢一張表,查詢最後的10位使用者資訊,由於B+樹索引是雙向連結串列,所以使用者可以快速找到最後一個數據頁,並取出10條記錄

聚集索引的好處之二:範圍查詢(range query),即如果要查詢主鍵某一範圍內的資料,通過葉子節點的上層中間節點就可以得到頁的範圍,之後直接讀取資料頁即可

輔助索引:

除了聚集索引其他所以都是輔助索引(Secondary Index,也成為非聚集索引)輔助索引與聚集索引

的區別是:輔助索引的葉子節點不包含行記錄的全部資料。

葉子節點除了包含鍵值以外,每個葉子節點中的索引行中還包含一個書籤(bookmark)。該書籤用

來告訴InnoDB儲存引擎去哪裡可以找到與索引相對應的行資料。

由於InnoDB儲存引擎是索引組織表,因此InnoDB儲存引擎的輔助索引的書籤就是相應行資料的聚集

索引鍵,

輔助索引的存在並不影響資料在聚集索引中的組織,因此每張表上可以有多個輔助索引,但只能有一

個聚集索引。當通過輔助索引來尋找資料時,InnoDB儲存引擎會遍歷輔助索引並通過葉子級別的指標

獲得只想主鍵索引的主鍵,然後再通過主鍵索引來找到一個完整的行記錄。

舉例來說,如果在一棵高度為3的輔助索引樹種查詢資料,那需要對這個輔助索引樹遍歷3次找到指定

主鍵,如果聚集索引樹的高度同樣為3,那麼還需要對聚集索引樹進行3次查詢,最終找到一個完整的

行資料所在的頁,因此一共需要6次邏輯IO訪問才能得到最終的一個數據頁。