Mysql索引主要包括四種,Btree索引、Hash索引、full-text全文索引、R-tree索引,因為作為一名PHP開發者,並不是專業的DBA,在這裡只需要瞭解第一種開發相關的BTree索引。
索引的本質:MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取資料和排序的資料結構。
資料庫查詢是資料庫的主要功能之一,最基本的查詢演算法是順序查詢(linear search)時間複雜度為O(n),顯然在資料量很大時效率很低。優化的查詢演算法如二分查詢(binary search)、二叉樹查詢(binary tree search)等,雖然查詢效率提高了。但是各自對檢索的資料都有要求:二分查詢要求被檢索資料有序,而二叉樹查詢只能應用於二叉查詢樹上,但是資料本身的組織結構不可能完全滿足各種資料結構(例如,理論上不可能同時將兩列都按順序進行組織)。所以,在資料之外,資料庫系統還維護著滿足特定查詢演算法的資料結構。這些資料結構以某種方式引用(指向)資料,這樣就可以在這些資料結構上實現高階查詢演算法。這種資料結構就是索引。
如上圖左邊是橫列表格,也就是真是的資料,右邊是一棵樹。資料越來越多,表格增長的越來越高,相反,如果樹越來越高,查詢的層次越來越多,我們如果能用三次找到,儘量別用四次,儘量減少一次磁碟I/O,也就是這棵樹廣度越來越廣,廣度廣了同一層就代表枝葉多。
在資料庫裡面,在物理儲存上,有單位的說法叫段、區、塊,就是一種衡量單位。 上圖中的磁塊也就是相當於儲存一段範圍的資料。
看上圖中,一棵B+樹,淺藍色的塊我們稱之為一個磁碟塊,可以看到每個磁碟塊包含幾個資料項(深藍色所示)和指標(黃色所示),如磁碟塊1包含資料項17和35,包含指標P1、P2、P3。
我如果要找29這個數字,那麼從根找,P1表示小與17的,P2表示大於17小與35的,P3表示大於35的,那麼往下走,真實的資料存在於葉子節點,也就是第三層,即3、5、9、10、13...依次往右看。假設我要查詢非葉子節點(第二層),不儲存真實的資料,只儲存指引搜尋方向的資料項,如17、35並不存在真實的資料表中,也就是相當於一個參考值。如果查詢29,但是我們先給參考項,那麼根據圖示,29在17和35之間,鎖定磁碟塊1的P2指標,找到指標P2,記憶體時間非常短,相比磁碟的IO可以忽略不計,那麼下來之後,找到磁碟塊3,也就是不見得載入磁碟塊2,這裡就第二次IO了,那麼看圖,29在26和30之間,那麼又指向指標P2,再往下就載入到了磁碟塊8的記憶體,發生第三次IO,同時記憶體中做二分查詢找到29,結束查詢,總共三次IO。
看Btree也就是三層樓那麼高,也就是儘量把資料橫向擴,高度矮比較好,真實的情況是,3層的B+樹 可以表示上百萬的資料,如果上百萬的資料查詢只需三次IO,效能提高將是巨大的,如果沒有所用,每個資料項都要發生一次IO,那麼總共需要上百萬次的IO,顯然成本非常高。