當有不少個數據的時候,以下圖右邊的兩個列表,順序查找會會遍歷每個元素,會很慢,尤爲是數據量很大的時候,遍歷整個表都會會一次都會消耗大量的時間mysql
結論:鏈表不得行算法
因而乎製做成二叉樹,以下圖右邊的樹。左邊的鏈表89號元素須要遍歷查找,而89的元素在在二叉樹中,一次比對後就完成了定位。因此單一個二叉樹就大大的優化了效率。
sql
mysql有使用二叉樹嗎
沒有,爲何呢?數據庫
想一想一下這個一個場景:有一堆連續的數組,放到二叉樹裏邊,那麼他的二叉樹結構就是一個鏈表的樣子!說明了說在個別場景中,二叉樹相對鏈表並無優點可言。
數組
紅黑樹(二叉平衡樹)
因而乎來到了紅黑樹,以下圖。數據結構
紅黑樹的應用比較普遍,主要是用它來存儲有序的數據,它的時間複雜度是O(lgn),效率很是之高。優化
補充紅黑樹的僞算法ui
這樣看起來,紅黑樹效率會高一些,可是爲何mysql用的不是紅黑樹呢
由於實際場景的時候,數據量會很大,好比幾百萬的時候,樹的層級可能達到20層,其實這個效率依然是不夠高。在數據量大的時候,查找速度慢,是無法避免的。spa
到這裏能夠得出,數據查詢的效率,跟數據層級是有關係的3d
因此這裏是否是能夠思考一下:咱們就讓這個紅黑樹高度可控,控制在一個指定的深度,好比就三層,就會快不少?
這樣子作得話,咱們只能在一個節點上,掛載更多的節點,而不是隻是兩個。
b樹和b+樹在底層存儲數據的區別,葉子節點有一個指針指向左右,這樣能夠按照順序地在葉子節點上遍歷數據。
在mysql中b+樹的特色
mysql的b+樹的第一層節點的大小是16kb。能夠經過sql語句查詢到:show global status liek "innodb_page_size"
。其實第一層大索引大體能夠存放(8+6)的數量是1170個的樣子,第二層的節點也是1170個樣樣子。第三場就單純存放索引,大概存放16個。
因此mysqlb+樹的索引,大概能夠存放的數據量在2000萬個左右。
其實實際狀況中,根節點的數據是常駐內存的,並非每次查詢都會從新載入一遍到內存。因此千萬級別的表,查找依然很快。
實際上b+樹的層級是能夠大於3層的,須要的話能夠設置。單實際上到這一步的時候,早就應該分庫分表的。也就是爲何mysql不建議存儲數據量大於2000萬行左右數據的一個緣由。
tips:
myisam引擎mysql數據文件夾裏邊的文件簡介:frm存放的是表結構,MYD是存放的數據,MYI存放的樹索引。
那麼myisam的數據內容,就是:
當查找col1(假如col1是索引)等於30是,就是去myi的的文件裏邊找,按照左邊的這個樹形結構,定位到數據地址,拉出裏邊的索引位置。經過索引記錄的位置,迅速定位到數據表的行的地址。這就是MYIsam
爲何要用innodb呢?
innodb的文件結構。
innodb在mysql數據庫文件夾下的數據文件格式是:
frm表明表結構文件, idb存放的既包含數據,又包含索引。這幾個名稱猴嘴的mysql文件,相信作過數據遷移的童鞋,都不會以爲陌生,甚至看到他會有一絲絲氣憤,當初就是這些讓本身常常加班!
因此能夠看出,innodb葉子節點上存放的不是索引,而直接是數據。Innodb的數據是直接掛在索引下的!
那麼這些差別,致使不一樣引擎的數據庫,都有哪些差別呢?
彙集索引(聚蔟索引):innodb葉子節點包含了完整數據的索引。
非彙集索引(離散索引):myslam 葉子節點上,沒有存放完整的數據。
uuid不合適,開篇死。由於uuid不是遞增的
由於innodb的數據,必須有一個b+樹的索引結構,來組織他的數據。mysql若是不創建主鍵,他就會進入這張表的第一列,判斷若是這列數據每個數據都是惟一的,那麼就用這一列當作索引。若是遍歷完了每一列,都沒有惟一的列,那麼mysql就會悄悄地爲你創建一列隱藏列。這樣一下走下來,就花費了太多運算了,因此推薦用戶自建自增索引。
爲何建議自增整形呢?(雪花算法也是自增的。)由於查找的時候須要常常比對大小,每一層會逐個比對大小,用asii碼去比對。而整形,在這一塊比對的時候會快一些,因此要求整形。爲甚自增呢?
爲了快。
好比遇到範圍查詢的時候,定位到了一個元素,是否是就很快能判斷上下位置的元素。
hash定位速度很快哦。超級快!
首先算hash值,而後根據hash存放在某個位置,這個數據裏邊存放了值和節點的地址。當有多個的時候,就在這個後邊直接添加。當數據量不大的時候,hash的效率很是高。
但實際上工做用絕大多數的時候都用的是b+而不是hash(99.99%都不是)。爲何呢?
b+樹的葉子節點有一個雙向指針,來保持數據的連貫性。此外b+數據幫咱們維護了一個從作到右的一種遞增結構。因此範圍查詢,只要定位到了上限或者下限,直接順藤摸瓜,很快就能完成定位。這也是爲何b+樹葉子節點要維護一個雙向指針的緣由。
即便你沒有按照順序存放數據,b+樹,也會幫你整理好順序。好比7,8,6,也會將6放到78前。因此若是不是遞增,調整順序會消耗計算,尤爲是在節點分裂的時候,要影響整個樹的結構的時候,結構變化就會佔用不少資源。可是若是順序存放,反正結構性調整的機率是比較低的,至關於也是加快了存儲的順序。
這也是添加了索引爲何會讓存儲變慢的底層緣由。
從上圖,能夠看一下二級索引的特色,二級索引緊貼在一級索引後邊,question:爲何二級索引長成這樣,實際使用時運做機制是什麼樣的。
想要理解多級索引的特色,其實,理解好mysql處理索引時,是如何爲多級索引排序的就行了。
其實查找時,方法就是逐個比對。若是第一層,就已經能夠比對處順序了,那麼這些數據,就直接就按這個順序來排就行。若是第一個索引大小相同,那就根據第二個來排序,若是第二個相同,就看第三個。若是第三個也相同,就看主鍵,若是沒有主鍵,那就看隱藏主鍵(因此創建自增索引很重要!)。