文本已收錄至個人GitHub倉庫,歡迎Star:github.com/bin39232820…
種一棵樹最好的時間是十年前,其次是如今
我知道不少人不玩qq了,可是懷舊一下,歡迎加入六脈神劍Java菜鳥學習羣,羣聊號碼:549684836 鼓勵你們在技術的路上寫博客mysql
咱們繼續來探索mysql。前面咱們瞭解了mysql的索引的一些基礎知識,今天咱們來康康B+樹索引git
前面把頁 ,頁中的槽。槽中的行,基本上一一聊清楚了,那麼咱們想呀,咱們的頁是放到哪裏的呢?它又有怎麼的結構呢?這個就是咱們今天要來討論的東西了。github
表空間是一個抽象的概念,對於系統表空間來講,對應着文件系統中一個或多個實際文件;對於每一個獨立表空間來講,對應着文件系統中一個名爲表名.ibd的實際文件。你們能夠把表空間想象成被切分爲許許多多個頁的池子,當咱們想爲某個表插入一條記錄的時候,就從池子中撈出一個對應的頁來把數據寫進去sql
表空間中的頁實在是太多了,爲了更好的管理這些頁面,設計InnoDB的大叔們提出了區(英文名:extent)的概念。對於16KB的頁來講,連續的64個頁就是一個區,也就是說一個區默認佔用1MB空間大小。不管是系統表空間仍是獨立表空間,均可以當作是由若干個區組成的,每256個區被劃分紅一組。畫個圖表示就是這樣:bash
表空間被劃分爲許多連續的區,每一個區默認由64個頁組成,每256個區劃分爲一組post
表空間的東西,太複雜。這邊就不先班門弄斧,若有有須要的就你們去看掘金小冊 MySQL 是怎樣運行的:從根兒上理解 MySQL學習
什麼意思呢?就是比如你要作一件事情,作這個事情的方法有不少種,好比咱們去美國,能夠坐飛機,作輪船,固然你也能夠走過去,哈哈地球畢竟是園的。優化
回到MySQL中來,咱們平時所寫的那些查詢語句本質上只是一種聲明式的語法,只是告訴MySQL咱們要獲取的數據符合哪些規則,至於MySQL背地裏是怎麼把查詢結果搞出來的那是MySQL本身的事兒。對於單個表的查詢來講,設計MySQL的大叔把查詢的執行方式大體分爲下邊兩種:spa
針對主鍵或惟一二級索引的等值查詢設計
針對普通二級索引的等值查詢
針對索引列的範圍查詢
直接掃描整個索引
把MySQL執行查詢語句的方式稱之爲訪問方法或者訪問類型。同一個查詢語句可能可使用多種不一樣的訪問方法來執行,雖然最後的查詢結果都是同樣的,可是執行的時間可能差老鼻子遠了,就像是從鐘樓到大雁塔,你能夠坐火箭去,也能夠坐飛機去,固然也能夠坐烏龜去。下邊細細道來各類訪問方法的具體內容。
有的時候咱們能夠經過主鍵列來定位一條記錄,比方說這個查詢:
SELECT * FROM liumaishenjian WHERE id = 1438;
對於liumaishenjian表的聚簇索引來講,展現的就是id列。咱們想突出的重點就是:B+樹葉子節點中的記錄是按照索引列排序的,對於的聚簇索引來講,它對應的B+樹葉子節點中的記錄就是按照id列排序的。B+樹原本就是一個矮矮的大胖子,因此這樣根據主鍵值定位一條記錄的速度賊快。相似的,咱們根據惟一二級索引列來定位一條記錄的速度也是賊快的,好比下邊這個查詢:
SELECT * FROM liumaishenjian WHERE key2 = 3841;
其實總結來講就是 經過主鍵索引 和 惟一二級索引的等值查詢就是很是快的,把這種經過主鍵或者惟一二級索引列來定位一條記錄的訪問方法定義爲:const,意思是常數級別的,代價是能夠忽略不計的。
有時候咱們對某個普通的二級索引列與常數進行等值比較,好比這樣:
SELECT * FROM liumaishenjian WHERE key1 = 'abc';
把這種搜索條件爲二級索引列與常數等值比較,採用二級索引來執行查詢的訪問方法稱爲:ref。咱們看一下采用ref訪問方法執行查詢的圖示:
從圖示中能夠看出,對於普通的二級索引來講,經過索引列進行等值比較後可能匹配到多條連續的記錄,而不是像主鍵或者惟一二級索引那樣最多隻能匹配1條記錄,因此這種ref訪問方法比const差了那麼一丟丟,可是在二級索引等值比較時匹配的記錄數較少時的效率仍是很高的(若是匹配的二級索引記錄太多那麼回表的成本就太大了),跟坐高鐵差很少。不過須要注意下邊兩種狀況:
二級索引列值爲NULL的狀況
不管是普通的二級索引,仍是惟一二級索引,它們的索引列對包含NULL值的數量並不限制,因此咱們採用key IS NULL這種形式的搜索條件最多隻能使用ref的訪問方法,而不是const的訪問方法。
對於某個包含多個索引列的二級索引來講,只要是最左邊的連續索引列是與常數的等值比較就可能採用ref的訪問方法
咱們以前介紹的幾種訪問方法都是在對索引列與某一個常數進行等值比較的時候纔可能使用到(ref_or_null比較奇特,還計算了值爲NULL的狀況),可是有時候咱們面對的搜索條件更復雜,好比下邊這個查詢:
SELECT * FROM liumaishenjian WHERE key2 IN (1438, 6328) OR (key2 >= 38 AND key2 <= 79);
複製代碼
咱們固然還可使用全表掃描的方式來執行這個查詢,不過也可使用二級索引 + 回表的方式執行,若是採用二級索引 + 回表的方式來執行的話,那麼此時的搜索條件就不僅是要求索引列與常數的等值匹配了,而是索引列須要匹配某個或某些範圍的值,在本查詢中key2列的值只要匹配下列3個範圍中的任何一個就算是匹配成功了:
若是把這幾個所謂的key2列的值須要知足的範圍在數軸上體現出來的話,那應該是這個樣子:
SELECT key_part1, key_part2, key_part3 FROM liumaishenjian WHERE key_part2 = 'abc';
複製代碼
前提條件 key_part1, key_part2, key_part3 是一個組合索引
因爲key_part2並非聯合索引idx_key_part最左索引列,因此咱們沒法使用ref或者range訪問方法來執行這個語句。可是呢他知足如下2個、條件
也就是說咱們能夠直接經過遍歷idx_key_part索引的葉子節點的記錄來比較key_part2 = 'abc'這個條件是否成立,把匹配成功的二級索引記錄的key_part1, key_part2, key_part3列的值直接加到結果集中就好了。因爲二級索引記錄比聚簇索記錄小的多(聚簇索引記錄要存儲全部用戶定義的列以及所謂的隱藏列,而二級索引記錄只須要存放索引列和主鍵),並且這個過程也不用進行回表操做,因此直接遍歷二級索引比直接遍歷聚簇索引的成本要小不少,設計MySQL的大叔就把這種採用遍歷二級索引記錄的執行方式稱之爲:index。
最直接的查詢執行方式就是咱們已經提了無數遍的全表掃描,對於InnoDB表來講也就是直接掃描聚簇索引,設計MySQL的大叔把這種使用全表掃描執行查詢的方式稱之爲:all。
咱們下章繼續再戰。
好了各位,以上就是這篇文章的所有內容了,能看到這裏的人呀,都是真粉。
創做不易,各位的支持和承認,就是我創做的最大動力,咱們下篇文章見
六脈神劍 | 文 【原創】若是本篇博客有任何錯誤,請批評指教,不勝感激 !